Introduction

Washington University Medical Center Redevelopment Corporation is a partnership between BJC Health Care and Washington University School of Medicine and works to improve the quality of life for the neighborhoods surrounding the medical campus. In order to achieve this goal in Forest Park Southeast and the Central West End , WUMCRC has invested millions of dollars toward regenerating the market for private investment in businesses and real estate, enhancing human and social service opportunities, and improving the level of physical and personal security.

One way we work to improve the level of physical & personal security is the analysis and distribution of data. The original source of this crime data is http://slmpd.org/crimereports.shtml. This notebook uses primarily compstatr to access and clean the crime data.

R Markdown

Tidy data

Create an Index

i <- cs_create_index()

Get Data - 2019

update <- cs_last_update()
update <- strsplit(update, " ")[[1]]
c_month <- update[[1]]
c_year <- as.numeric(update[[2]])
yearList19 <- cs_get_data(year = c_year, index = i)

Download Current Month

cs_validate(yearList19, year = 2019)
[1] TRUE
totalCrimes19 <- cs_collapse(yearList19)
print(c_month)
[1] "August"
crimes19 <- cs_extract_month(yearList19, month = "August") 

Clean & Categorize Data - 2019

cs_filter_count removes negative counts. Negative counts, -1, in the count column means that the crime, or charge in this specific observation has either been deemed unfounded, or the crime has been up coded. We do not want to map this data.

Many of the analyses we conduct include comparisons between violent & non-violent crime, comparisons on the amount of crimes happening in each crime cateogy over time, and if crimes occur during the day or at night. The following code ceates variables to conduct these analyses.

cs_crime_cat creates a variable with the names of the crime.

cs_crime creates a logic variable and codes violent crimes as TRUE and non-violent crimes as FALSE

cs_parse_date creates two columns separating the Date Occur variable. The two colums are as follows: one contains the date - month, date, and year, and the other contains the hour and minute. This is used because crimes coded in the most recent month, can contain dates that occured, in previous months or years & in this report we only want to map the crimes that occured in the past month.

filter is a dplyr function that filters out any dates that occur before the our selected date, and also filters out crimes that did not happen in either District 2 or district 5.

mutate adds a variable that codes and labels the days of the week for each crime that occurred, and creates another time of day variable

tidyCrimes19 <- crimes19 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(dateOcc >= as.Date("2019-08-01")) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc)

tidyCrimes19$neighborhood <- as.numeric(tidyCrimes19$neighborhood)

strptime and format takes the new time variable and formats it to a character so that we can determine if the crime occured at day or at night, and creates a second coded variable that labels each observations as day or night based on the newly formated time variable.

select drops the unneeded variables.

cs_missing_XY determines what data does not have x & y coordinates, and therefore cannot be accurately mapped.

cs_replace0 replaces missing x & y coordinates with NA, and drops the missing data.

tidyCrimes19$tod <- strptime(tidyCrimes19$tod, tz = "America/Chicago", "%H:%M")
tidyCrimes19$tod <- format(tidyCrimes19$tod, format = "%H%M%S")

tidyCrimes19 <- tidyCrimes19 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyCrimes19 <- cs_missingXY(tidyCrimes19, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyCrimes19$missing)

FALSE  TRUE 
  735     4 
tidyCrimes19 <- tidyCrimes19 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE) 

Total Crimes 2019 - Clean

totalYearlyCrimes19 <- cs_collapse(yearList19)

tidyTotalCrimes19 <- totalYearlyCrimes19 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_month(., var = coded_month, yearVar = reportYear, month = monthVar) %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc) 

tidyTotalCrimes19$neighborhood <- as.numeric(tidyTotalCrimes19$neighborhood)

tidyTotalCrimes19$tod <- strptime(tidyTotalCrimes19$tod, tz = "America/Chicago", "%H:%M")
tidyTotalCrimes19$tod <- format(tidyTotalCrimes19$tod, format = "%H%M%S")

tidyTotalCrimes19 <- tidyTotalCrimes19 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyTotalCrimes19 <- cs_missingXY(tidyTotalCrimes19, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyTotalCrimes19$missing)

FALSE  TRUE 
 5236    87 
tidyTotalCrimes19 <- tidyTotalCrimes19 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE)

rm(totalCrimes18)
object 'totalCrimes18' not found

Get Data - 2018

yearList18 <- cs_get_data(year = 2018, index = i)

Data Preperation

cs_validate(yearList18, year = 2018)
[1] TRUE

Download Last Year’s Month

totalCrimes18 <- cs_collapse(yearList18)
monthCrimes18 <- cs_extract_month(yearList18, month = "August")
rm(yearList18)

Clean & Categorize Data - 2018

tidyMonthCrimes18 <- monthCrimes18 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(dateOcc >= as.Date("2018-08-01") & dateOcc <= as.Date("2018-08-31")) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc)

tidyMonthCrimes18$neighborhood <- as.numeric(tidyMonthCrimes18$neighborhood)

tidyMonthCrimes18$tod <- strptime(tidyMonthCrimes18$tod, tz = "America/Chicago", "%H:%M")
tidyMonthCrimes18$tod <- format(tidyMonthCrimes18$tod, format = "%H%M%S")

tidyMonthCrimes18 <- tidyMonthCrimes18 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyMonthCrimes18 <- cs_missingXY(tidyMonthCrimes18, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyMonthCrimes18$missing)

FALSE  TRUE 
  747     9 
tidyMonthCrimes18 <- tidyMonthCrimes18 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE)
tidyTotalCrimes18 <- totalCrimes18 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_month(., var = coded_month, yearVar = reportYear, month = monthVar) %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc) 

tidyTotalCrimes18$neighborhood <- as.numeric(tidyTotalCrimes18$neighborhood)

tidyTotalCrimes18$tod <- strptime(tidyTotalCrimes18$tod, tz = "America/Chicago", "%H:%M")
tidyTotalCrimes18$tod <- format(tidyTotalCrimes18$tod, format = "%H%M%S")

tidyTotalCrimes18 <- tidyTotalCrimes18 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyTotalCrimes18 <- cs_missingXY(tidyTotalCrimes18, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyTotalCrimes18$missing)

FALSE  TRUE 
 7729   139 
tidyTotalCrimes18 <- tidyTotalCrimes18 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE)

rm(totalCrimes18)

Combine 2018 & 2019

augustCrimes <- rbind(tidyMonthCrimes18, tidyCrimes19)

Create Spatial Objects

crimesYear18_sf <- cs_projectXY(tidyTotalCrimes18, varX = x_coord, varY = y_coord, crs = 102696)
crimes19_sf <- cs_projectXY(tidyCrimes19, varX = x_coord, varY = y_coord, crs = 102696)
augustCrimes_sf <- cs_projectXY(augustCrimes, varX = x_coord, varY = y_coord, crs = 102696)

Prep for Data by Neighborhood

sa <- c(39,28,38,51,53,54,58,46,47,48,48)
dst2 <- c(7:15,27:29, 39:45,81,82,87,88)
dst5 <- c(38,46:58,78)

Mapping

One way we work to improve the level of physical & personal security is the analysis and distribution of crime data and statistics. The original source of this crime data is http://slmpd.org/crimereports.shtml. This notebook takes the data that was previously cleaned and maps the data.

Load Spatial Data

Coordinates

xyfpse <- c(-90.2679, -90.2423, 38.6176, 38.6334)
xycwe <- c(-90.2759, -90.2368, 38.6286, 38.6552)
xybot <- c(-90.2619, -90.2409, 38.6165, 38.6296)
xydbp <- c(-90.2869, -90.2726, 38.6433, 38.6566)
xysdb <- c(-90.3026, -90.2827, 38.6456, 38.6571)
xywe <- c(-90.3020, -90.2712, 38.6517, 38.6710)
xyvp <- c(-90.2803, -90.2712, 38.6517, 38.6622)
xyac <- c(-90.2744, -90.2609, 38.6505, 38.6661)
xyfp <- c(-90.2648, -90.2543, 38.6493, 38.6655)
xylp <- c(-90.2588, -90.2437, 38.6481, 38.6624)
xyvd <- c(-90.2520, -90.2304, 38.6426, 38.6585)
xymc <- c(-90.2678, -90.2515, 38.6305, 38.6411)
xyctx <- c(-90.2581, -90.2419, 38.6299, 38.6386)
xygrv <- c(-90.2662, -90.2440, 38.6238, 38.6318)
xydst2 <- c(-90.3203, -90.2297, 38.5613, 38.6493)
xydst5 <- c(-90.3080, -90.2132, 38.6273, 38.6962)

Open Street Map from Mapbox - Basemap Tile Imagery

Load External Data

Population Data

load(here("data/nbhd_pop10.rda"))

Spatial

Combine Population & Neighborhood Spatial Data by Police District

Oganize & Filter Crime Data by Neighborhood

dst_2 <- tidyCrimes19 %>% 
  filter(., neighborhood %in% dst2) %>% 
  group_by(., neighborhood) %>%
  count() %>% 
  rename(crimeTotal = n) %>%
  left_join(nbhd_pop10, by = "neighborhood") %>% 
  mutate(., crimeRate = (crimeTotal/pop10)*1000) %>% 
  drop_na()
dst_5 <- tidyCrimes19 %>% 
  filter(., neighborhood %in% dst5) %>% 
  group_by(., neighborhood) %>%
  count() %>% 
  rename(crimeTotal = n) %>%
  left_join(nbhd_pop10, by = "neighborhood") %>% 
  mutate(., crimeRate = (crimeTotal/pop10)*1000) %>% 
  drop_na()
dst_2_pop <- left_join(nhoods_sf, dst_2, by = "neighborhood") %>% 
  st_transform(crs = 102696) %>%
  drop_na() %>% 
  subset(., neighborhood != 88)
dst_5_pop <- left_join(nhoods_sf, dst_5, by = "neighborhood") %>% 
  st_transform(crs = 102696) %>%
  drop_na()

FPSE, BOT, CWE, MC

Map Creation

FPSE
fpse_total_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 39) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_total_tm

fpse_dn_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 39) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "dayNight", 
               palette = "-RdBu", 
               title.col = "Time of Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Time of Crimes - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_dn_tm

fpse_vlnt_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 39) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "violent", 
               palette = "Reds", 
               title.col = "Violent") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Violent Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_vlnt_tm

crimes19_sf %>%
  filter(neighborhood == 39) %>%
  smooth_map(., bandwidth = 0.5, style = "pretty",
  cover = fpse) -> fpse_densities

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |=========                                                                                   |  10%
  |                                                                                                  
  |============================                                                                |  30%
  |                                                                                                  
  |==============================================                                              |  50%
  |                                                                                                  
  |================================================================                            |  70%
  |                                                                                                  
  |===================================================================================         |  90%
  |                                                                                                  
  |============================================================================================| 100%
fpse_den_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = NA, 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(fpse_densities$polygons) +
  tm_fill(col = "level", palette = "BuPu", alpha = .60, 
    title = expression("Crimes per " * km^2)) +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Crime Density - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_den_tm

Grove CID
grove_crimes <- st_intersection(crimes19_sf, grove_cid)
attribute variables are assumed to be spatially constant throughout all geometries
fpse_grove_tm <- tm_shape(grv_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(grove_cid) +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 1, 
               lty = "solid") +
  tm_shape(grove_crimes) +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Grove CID Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_grove_tm

CWE
cwe_total_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 38) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_total_tm

cwe_dn_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 38) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "dayNight", 
               palette = "-RdBu", 
               title.col = "Time of Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_dn_tm

cwe_vlnt_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 38) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "violent", 
               palette = "Reds", 
               title.col = "Violent") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Time of Crimes - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_vlnt_tm

cwe_densities <- crimes19_sf %>%
  filter(neighborhood == 38) %>%
  smooth_map(., bandwidth = 0.5, style = "pretty",
  cover = cwe)

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |=========                                                                                   |  10%
  |                                                                                                  
  |============================                                                                |  30%
  |                                                                                                  
  |==============================================                                              |  50%
  |                                                                                                  
  |================================================================                            |  70%
  |                                                                                                  
  |===================================================================================         |  90%
  |                                                                                                  
  |============================================================================================| 100%
cwe_den_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = NA, 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(cwe_densities$polygons) +
  tm_fill(col = "level", palette = "BuPu", alpha = .60, 
    title = expression("Crimes per " * km^2)) +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Crime Density- August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_den_tm

Medical Campus
mc_crimes <- st_intersection(crimes19_sf, med_campus)
attribute variables are assumed to be spatially constant throughout all geometries
cwe_mc_tm <- tm_shape(mc_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(med_campus) +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 1, 
               lty = "solid") +
  tm_shape(mc_crimes) +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Med. Campus Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_mc_tm


mc_crimes_18 <- st_intersection(crimesYear18_sf, med_campus) %>% 
  as.data.frame()
attribute variables are assumed to be spatially constant throughout all geometries
mc_crimes <- mc_crimes %>% 
   as.data.frame()

mc_crimes_18 %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08",
         "September" = "09",
         "October" = "10",
         "November" = "11",
         "December" = "12") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> mc_2018

mc_crimes %>% 
  group_by(crimeCatName) %>% 
  count() %>% 
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Part 1 Crimes" = crimeCatName) -> mc_crimeCat

kable(mc_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("mc_crimCat.jpeg")

mc_crimes %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> mc_dayNight

kable(mc_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("mc_dayNight.jpeg")

mc_larcenies <- mc_crimes %>% 
  filter(., crimeCatNum == 6)

write.csv(mc_larcenies, file = here("results/cwe/2019/august/cwe_larcenies.csv"))

write.csv(mc_crimes, file = here("results/cwe/2019/august/mc_crimes_august19.csv"))
write.csv(mc_2018, file = here("results/cwe/2019/august/mc_crimes_2018.csv"))
Cortex
ctx_crimes <- st_intersection(crimes19_sf, cortex)
attribute variables are assumed to be spatially constant throughout all geometries
cwe_ctx_tm <- tm_shape(ctx_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(cortex) +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 1, 
               lty = "solid") +
  tm_shape(ctx_crimes) +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Cortex Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_ctx_tm

Botanical Heights
bot_total_tm <- tm_shape(bot_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 28) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 28) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Botanical Heights Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

bot_total_tm

District 2 Density Maps
dst2_rateMap <- tm_shape(dst2_tiles) +
  tm_rgb() +
  tm_shape(dst_2_pop) +
  tm_polygons(col = "crimeRate",
              palette = "BuPu",
              style = "jenks",
              title = "Crimes per 1,000 Residents") +
  tm_text("neighborhood", shadow=TRUE) +
  tm_layout(
    main.title = "District 2 Crime Rates - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

dst2_rateMap

dst_2_statsTotal <- describe(dst_2_pop$crimeTotal)
dst_2_statsRate <- describe(dst_2_pop$crimeRate)

dst_2_statsTotal
dst_2_statsRate
dst5_rateMap <- tm_shape(dst5_tiles) +
  tm_rgb() +
  tm_shape(dst_5_pop) +
  tm_polygons(col = "crimeRate",
              palette = "BuPu",
              style = "jenks",
              title = "Crimes per 1,000 Residents") +
  tm_text("neighborhood", shadow=TRUE) +
  tm_layout(
    main.title = "District 5 Crime Rates - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

dst5_rateMap

dst_5_statsTotal <- describe(dst_5_pop$crimeTotal)
dst_5_statsRate <- describe(dst_5_pop$crimeRate)

dst_5_statsTotal
dst_5_statsRate

Save Maps

Clean Workspace

rm(fpse_total_tm, fpse_dn_tm, fpse_vlnt_tm, fpse_den_tm, fpse_grove_tm, cwe_total_tm, cwe_dn_tm, cwe_vlnt_tm, cwe_den_tm, cwe_mc_tm, cwe_ctx_tm, bot_total_tm, fpse_tiles, cwe_tiles, bot_tiles, mc_tiles, ctx_tiles, grv_tiles, dst_2, dst_5, dst2_tiles, dst5_tiles)

Tables

FPSE Tables

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(crimeCatName) %>% 
  count() %>% 
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Part 1 Crimes" = crimeCatName) -> fpse_crimeCat

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(weekday) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Day of the Week" = weekday) -> fpse_weekDay

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(violent) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Crimes Against Persons" = violent) -> fpse_violent


tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> fpse_dayNight

tidyTotalCrimes18 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08",
         "September" = "09",
         "October" = "10",
         "November" = "11",
         "December" = "12") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> fpse_2018

tidyTotalCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> fpse_2019

fpse_larcenies <- tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  filter(., crimeCatNum == 6)

write.csv(fpse_larcenies, file = here("results/fpse/2019/august/larcenies.csv"))

fpse_larcenies %>% 
  group_by(weekday) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Day of the Week" = weekday) -> fpse_larcenies_weekDay

fpse_larcenies %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> fpse_larcenies_dayNight
kable(fpse_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_crimCat.jpeg")

kable(fpse_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_weekDay.jpeg")

kable(fpse_violent) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_violent.jpeg")

kable(fpse_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_dayNight.jpeg")

kable(fpse_2018) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_2018.jpeg")

kable(fpse_2019) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_2019.jpeg")

kable(fpse_larcenies_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_larcenies_weekDay.jpeg")

kable(fpse_larcenies_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_larcenies_dayNight.jpeg")

CWE Tables

kable(cwe_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_crimCat.jpeg")

kable(cwe_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_weekDay.jpeg")

kable(cwe_violent) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_violent.jpeg")

kable(cwe_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_dayNight.jpeg")

kable(cwe_2018) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_2018.jpeg")

kable(cwe_2019) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_2019.jpeg")

kable(cwe_larcenies_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_larcenies_weekDay.jpeg")

kable(cwe_larcenies_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_larcenies_dayNight.jpeg")
head(fpse_2018) 
       Part 1 Crimes January February March April May June July August September October November
  Aggravated Assault       2        2     0     3   7    5    4      3         1       7        0
            Homicide       1        0     0     0   0    0    0      0         0       0        0
             Larceny       5        3     6     7  20    5   13     12        14       9       10
 Motor Vehicle Theft       2        1     2     0   3    3    3      2         2       2        2
            Burgalry       0        1     1     3   0    1    1      1         0       1        0
               Arson       0        0     1     0   0    0    0      0         0       0        0
 December Total
        3    37
        0     1
        3   107
        2    24
        0     9
        0     1
write.csv(fpse_2018, file = here("results/fpse/2019/august/fpse_2018.csv"))
head(fpse_2019)
       Part 1 Crimes January February March April May June July August Total
             Larceny       8       10    14    12   8   20   17     19   108
 Motor Vehicle Theft       3        6     1     2   0    2    7      2    23
             Robbery       1        0     1     1   2    5    2      1    13
  Aggravated Assault       0        3     1     2   2    4    2      0    14
               Arson       0        0     1     0   0    0    1      0     2
            Burgalry       0        0     1     1   0    0    3      1     6
write.csv(fpse_2019, file = here("results/fpse/2019/august/fpse_2019.csv"))
head(cwe_2018)
       Part 1 Crimes January February March April May June July August September October November
  Aggravated Assault       7        0     1     7   6   11    6      4         7       4        4
            Burgalry       4        5     6     7   6   13   10     15         7       9       11
            Homicide       1        0     0     0   0    0    0      0         0       0        0
             Larceny      95       61    52    53  65   90  131     89        75      82       60
 Motor Vehicle Theft       9        6     7     9  12    6    6      5        10      12        6
             Robbery       2        2     8    10   1    8    3      9         6       8        5
 December Total
       10    67
        2    95
        0     1
       53   906
        9    97
        6    68
write.csv(cwe_2018, file = here("results/cwe/2019/august/cwe_2018.csv"))
head(cwe_2019)
       Part 1 Crimes January February March April May June July August Total
  Aggravated Assault       8        4    10     3   8   14    4     10    61
            Burgalry       3        5     5     9  13    7   12     18    72
             Larceny      49       63    65    66  68   60   76     78   525
 Motor Vehicle Theft      12        8     3    10  12   10    5     11    71
             Robbery       5        5     2     6   7    3    4      8    40
               Arson       0        0     1     0   0    0    0      0     1
write.csv(cwe_2019, file = here("results/cwe/2019/august/cwe_2019.csv"))

Botanical Heights

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(crimeCatName) %>% 
  count() %>% 
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Part 1 Crimes" = crimeCatName) -> bot_crimeCat

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(weekday) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Day of the Week" = weekday) -> bot_weekDay

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(violent) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Crimes Against Persons" = violent) -> bot_violent


tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> bot_dayNight

tidyTotalCrimes18 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08",
         "September" = "09",
         "October" = "10",
         "November" = "11",
         "December" = "12") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> bot_2018
write.csv(bot_2018, file = here("results/bot/2019/bot_2018.csv"))

tidyTotalCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> bot_2019
write.csv(bot_2019, file = here("results/bot/2019/bot_2019.csv"))
kable(bot_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_crimCat.jpeg")

kable(bot_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_weekDay.jpeg")

kable(bot_violent) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_violent.jpeg")

kable(bot_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_dayNight.jpeg")

Graphs/Charts

need to change file save locations

FPSE Graphs

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(weekday) %>% 
  count() %>%
  ggplot(., aes(x=weekday, y=n, group=1)) +
    geom_line(color="blue") +
    geom_point() + 
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("FPSE Total Crimes by Days of the Week")

ggsave(here("results/graphs/fpse_crime_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(crimeCatName) %>%
  ggplot(., aes(weekday)) +
    geom_bar(aes(fill = crimeCatName), position=position_dodge()) +
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("FPSE Crimes by Day & Category") + 
    labs(fill = "Part 1 Crimes") +
    scale_fill_brewer(palette = "Spectral")

ggsave(here("results/graphs/fpse_crimeCat_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(dayNight) %>%
  count() %>% 
  ggplot(., aes(x=dayNight, y=n, fill = dayNight)) +
    geom_bar(stat="identity", position=position_dodge(), colour="black") +
    xlab("Time of Day") + ylab("Total Crimes") +
    ggtitle("FPSE Crimes by Time of Day") + 
    labs(fill = "Time")

ggsave(here("results/graphs/fpse_crime_timeDay.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

CWE Graphs

tidyCrimes19 %>% 
  filter(., neighborhood == 38) %>% 
  group_by(weekday) %>% 
  count() %>%
  ggplot(., aes(x=weekday, y=n, group=1)) +
    geom_line(color="blue") +
    geom_point() + 
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("CWE Total Crimes by Days of the Week")

ggsave(here("results/graphs/cwe_crime_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 38) %>% 
  group_by(crimeCatName) %>%
  ggplot(., aes(weekday)) +
    geom_bar(aes(fill = crimeCatName), position=position_dodge()) +
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("CWE Crimes by Day & Category") + 
    labs(fill = "Part 1 Crimes") +
    scale_fill_brewer(palette = "Spectral")

ggsave(here("results/graphs/cwe_crimeCat_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 38) %>% 
  group_by(dayNight) %>%
  count() %>% 
  ggplot(., aes(x=dayNight, y=n, fill = dayNight)) +
    geom_bar(stat="identity", position=position_dodge(), colour="black") +
    xlab("Time of Day") + ylab("Total Crimes") +
    ggtitle("CWE Crimes by Time of Day") + 
    labs(fill = "Time") 

ggsave(here("results/graphs/cwe_crime_timeDay.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

BOT

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(weekday) %>% 
  count() %>%
  ggplot(., aes(x=weekday, y=n, group=1)) +
    geom_line(color="blue") +
    geom_point() + 
    expand_limits(y=0) +
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("BOT Total Crimes by Days of the Week")

ggsave(here("results/graphs/bot_crime_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

LS0tCnRpdGxlOiAiU2FpbnQgTG91aXMgQ2l0eSBDcmltZSBEYXRhIC0gTW9udGhseSBSZXBvcnRzIgphdXRob3I6ICJKZXMgU3RldmVucywgTS5BLiIKZGF0ZTogJyhgciBmb3JtYXQoU3lzLnRpbWUoKSwgIiVCICVkLCAlWSIpYCknCm91dHB1dDoKICBnaXRodWJfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CmFsd2F5c19hbGxvd19odG1sOiB5ZXMKLS0tCgpgYGB7ciBTZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIEludHJvZHVjdGlvbiAKCltXYXNoaW5ndG9uIFVuaXZlcnNpdHkgTWVkaWNhbCBDZW50ZXIgUmVkZXZlbG9wbWVudCBDb3Jwb3JhdGlvbl0oaHR0cDovL3d1bWNyYy5jb20pIGlzIGEgcGFydG5lcnNoaXAgYmV0d2VlbiBCSkMgSGVhbHRoIENhcmUgYW5kIFdhc2hpbmd0b24gVW5pdmVyc2l0eSBTY2hvb2wgb2YgTWVkaWNpbmUgYW5kIHdvcmtzIHRvIGltcHJvdmUgdGhlIHF1YWxpdHkgb2YgbGlmZSBmb3IgdGhlIG5laWdoYm9yaG9vZHMgc3Vycm91bmRpbmcgdGhlIG1lZGljYWwgY2FtcHVzLiBJbiBvcmRlciB0byBhY2hpZXZlIHRoaXMgZ29hbCBpbiBGb3Jlc3QgUGFyayBTb3V0aGVhc3QgYW5kIHRoZSBDZW50cmFsIFdlc3QgRW5kICwgV1VNQ1JDIGhhcyBpbnZlc3RlZCBtaWxsaW9ucyBvZiBkb2xsYXJzIHRvd2FyZCByZWdlbmVyYXRpbmcgdGhlIG1hcmtldCBmb3IgcHJpdmF0ZSBpbnZlc3RtZW50IGluIGJ1c2luZXNzZXMgYW5kIHJlYWwgZXN0YXRlLCBlbmhhbmNpbmcgaHVtYW4gYW5kIHNvY2lhbCBzZXJ2aWNlIG9wcG9ydHVuaXRpZXMsIGFuZCBpbXByb3ZpbmcgdGhlIGxldmVsIG9mIHBoeXNpY2FsIGFuZCBwZXJzb25hbCBzZWN1cml0eS4KCk9uZSB3YXkgd2Ugd29yayB0byBpbXByb3ZlIHRoZSBsZXZlbCBvZiBwaHlzaWNhbCAmIHBlcnNvbmFsIHNlY3VyaXR5IGlzIHRoZSBhbmFseXNpcyBhbmQgZGlzdHJpYnV0aW9uIG9mIGRhdGEuIFRoZSBvcmlnaW5hbCBzb3VyY2Ugb2YgdGhpcyBjcmltZSBkYXRhIGlzIDxodHRwOi8vc2xtcGQub3JnL2NyaW1lcmVwb3J0cy5zaHRtbD4uIFRoaXMgbm90ZWJvb2sgdXNlcyBwcmltYXJpbHkgYGNvbXBzdGF0cmAgdG8gYWNjZXNzIGFuZCBjbGVhbiB0aGUgY3JpbWUgZGF0YS4gCgojIyBSIE1hcmtkb3duCgpgYGB7ciBMb2FkIERlcGVuZGVuY2llcywgaW5jbHVkZSA9IEZBTFNFfQojIHRpZHl2ZXJzZSBwYWNrYWdlcwpsaWJyYXJ5KGdncGxvdDIpICAgICAgICMgcGxvdHRpbmcgZGF0YQpsaWJyYXJ5KHN0cmluZ3IpICAgICAgICMgd3JhcHBlcnMgZm9yIGNvbW1vbiBzdHJpbmcgb3BlcmF0aW9ucwpsaWJyYXJ5KHRpZHlyKSAgICAgICAgICMgdGlkeSBkYXRhCmxpYnJhcnkoZHBseXIpICAgICAgICAgIyBkYXRhIG1hbmlwdWxhdGlvbgpsaWJyYXJ5KG1hZ3JpdHRyKSAgICAgICMgcGlwZSBvcGVyYXRvcgpsaWJyYXJ5KHJlYWR4bCkgICAgICAgICMgcmVhZCAmIHdyaXRlIGV4Y2VsIGZpbGVzCmxpYnJhcnkobHVicmlkYXRlKQoKIyBzcGF0aWFsIHBhY2thZ2VzCmxpYnJhcnkodG1hcCkgICAgICAgICAjIG1hcCBsYXlvdXRzCmxpYnJhcnkodG1hcHRvb2xzKSAgICAjIHRvb2xzIGZvciBoYW5kZWxpbmcgc3BhdGlhbCAKbGlicmFyeShvbGR0bWFwdG9vbHMpCmxpYnJhcnkoc2YpICAgICAgICAgICAjIHNwYXRpYWwgZGF0YSB0b29scwpsaWJyYXJ5KGNlcmFtaWMpICAgICAgIyBkb3dubG9hZCBvbmxpbmUgaW1hZ2VyeSB0aWxlcwpsaWJyYXJ5KGNvbXBzdGF0cikgICAgIyB0b29scyBmb3IgU1RMIGNyaW1lIGRhdGEKbGlicmFyeShyYXN0ZXIpICAgICAgICMgZ2VvZ3JhcGljIGRhdGEgYW5hbHlzaXMgJiBtb2RlbGluZwoKIyBvdGhlciBwYWNrYWdlcwpsaWJyYXJ5KGhlcmUpICAgICAgICAgIyBmaWxlIHBhdGggbWFuYWdlbWVudApsaWJyYXJ5KFJDb2xvckJyZXdlcikgIyBjeW50aGlhIGJyZXdlciBjb2xvciBwYWxldHRlcwpsaWJyYXJ5KHZpcmlkaXMpICAgICAgIyBjb2xvciBwYWxldHRlcwpsaWJyYXJ5KGthYmxlRXh0cmEpICAgIyBleHBvcnRpbmcgcHJldHR5IHRhYmxlcwpsaWJyYXJ5KGphbml0b3IpICAgICAgIyB0b29scyBmb3IgZXhhbWluaW5nIGRhdGEKYGBgCgojIyBUaWR5IGRhdGEKCiMjIyBDcmVhdGUgYW4gSW5kZXgKCmBgYHtyIENyZWF0ZSBDcmltZSBJbmRleH0KaSA8LSBjc19jcmVhdGVfaW5kZXgoKQpgYGAKCiMjIyBHZXQgRGF0YSAtIDIwMTkKCmBgYHtyIFB1bGwgMjAxOSBEYXRhfQp1cGRhdGUgPC0gY3NfbGFzdF91cGRhdGUoKQp1cGRhdGUgPC0gc3Ryc3BsaXQodXBkYXRlLCAiICIpW1sxXV0KY19tb250aCA8LSB1cGRhdGVbWzFdXQpjX3llYXIgPC0gYXMubnVtZXJpYyh1cGRhdGVbWzJdXSkKeWVhckxpc3QxOSA8LSBjc19nZXRfZGF0YSh5ZWFyID0gY195ZWFyLCBpbmRleCA9IGkpCmBgYAoKIyMjIERvd25sb2FkIEN1cnJlbnQgTW9udGgKCmBgYHtyIFZhbGlkYXRlIDIwMTkgRGF0YX0KY3NfdmFsaWRhdGUoeWVhckxpc3QxOSwgeWVhciA9IDIwMTkpCmBgYAoKYGBge3IgU3RhbmRhcmRpemUgMjAxOSBEYXRhfQp0b3RhbENyaW1lczE5IDwtIGNzX2NvbGxhcHNlKHllYXJMaXN0MTkpCmBgYAoKCmBgYHtyIFByaW50IEN1cnJlbnQgTW9udGh9CnByaW50KGNfbW9udGgpCmBgYAoKCmBgYHtyIEV4dHJhY3QgQXVndXN0IDIwMTkgRGF0YX0KY3JpbWVzMTkgPC0gY3NfZXh0cmFjdF9tb250aCh5ZWFyTGlzdDE5LCBtb250aCA9ICJBdWd1c3QiKSAKYGBgCgojIyMgQ2xlYW4gJiBDYXRlZ29yaXplIERhdGEgLSAyMDE5CgpgY3NfZmlsdGVyX2NvdW50YCByZW1vdmVzIG5lZ2F0aXZlIGNvdW50cy4gTmVnYXRpdmUgY291bnRzLCAtMSwgaW4gdGhlIGNvdW50IGNvbHVtbiBtZWFucyB0aGF0IHRoZSBjcmltZSwgb3IgY2hhcmdlIGluIHRoaXMgc3BlY2lmaWMgb2JzZXJ2YXRpb24gaGFzIGVpdGhlciBiZWVuIGRlZW1lZCB1bmZvdW5kZWQsIG9yIHRoZSBjcmltZSBoYXMgYmVlbiB1cCBjb2RlZC4gV2UgZG8gbm90IHdhbnQgdG8gbWFwIHRoaXMgZGF0YS4gCgpNYW55IG9mIHRoZSBhbmFseXNlcyB3ZSBjb25kdWN0IGluY2x1ZGUgY29tcGFyaXNvbnMgYmV0d2VlbiB2aW9sZW50ICYgbm9uLXZpb2xlbnQgY3JpbWUsIGNvbXBhcmlzb25zIG9uIHRoZSBhbW91bnQgb2YgY3JpbWVzIGhhcHBlbmluZyBpbiBlYWNoIGNyaW1lIGNhdGVvZ3kgb3ZlciB0aW1lLCBhbmQgaWYgY3JpbWVzIG9jY3VyIGR1cmluZyB0aGUgZGF5IG9yIGF0IG5pZ2h0LiBUaGUgZm9sbG93aW5nIGNvZGUgY2VhdGVzIHZhcmlhYmxlcyB0byBjb25kdWN0IHRoZXNlIGFuYWx5c2VzLiAKCmBjc19jcmltZV9jYXRgIGNyZWF0ZXMgYSB2YXJpYWJsZSB3aXRoIHRoZSBuYW1lcyBvZiB0aGUgY3JpbWUuIAoKYGNzX2NyaW1lYCBjcmVhdGVzIGEgbG9naWMgdmFyaWFibGUgYW5kIGNvZGVzIHZpb2xlbnQgY3JpbWVzIGFzIGBUUlVFYCBhbmQgbm9uLXZpb2xlbnQgY3JpbWVzIGFzIGBGQUxTRWAKCmBjc19wYXJzZV9kYXRlYCBjcmVhdGVzIHR3byBjb2x1bW5zIHNlcGFyYXRpbmcgdGhlIGBEYXRlIE9jY3VyYCB2YXJpYWJsZS4gVGhlIHR3byBjb2x1bXMgYXJlIGFzIGZvbGxvd3M6IG9uZSBjb250YWlucyB0aGUgZGF0ZSAtIG1vbnRoLCBkYXRlLCBhbmQgeWVhciwgYW5kIHRoZSBvdGhlciBjb250YWlucyB0aGUgaG91ciBhbmQgbWludXRlLiBUaGlzIGlzIHVzZWQgYmVjYXVzZSBjcmltZXMgY29kZWQgaW4gdGhlIG1vc3QgcmVjZW50IG1vbnRoLCBjYW4gY29udGFpbiBkYXRlcyB0aGF0IG9jY3VyZWQsIGluIHByZXZpb3VzIG1vbnRocyBvciB5ZWFycyAmIGluIHRoaXMgcmVwb3J0IHdlIG9ubHkgd2FudCB0byBtYXAgdGhlIGNyaW1lcyB0aGF0IG9jY3VyZWQgaW4gdGhlIHBhc3QgbW9udGguIAoKYGZpbHRlcmAgaXMgYSBgZHBseXJgIGZ1bmN0aW9uIHRoYXQgZmlsdGVycyBvdXQgYW55IGRhdGVzIHRoYXQgb2NjdXIgYmVmb3JlIHRoZSBvdXIgc2VsZWN0ZWQgZGF0ZSwgYW5kIGFsc28gZmlsdGVycyBvdXQgY3JpbWVzIHRoYXQgZGlkIG5vdCBoYXBwZW4gaW4gZWl0aGVyIERpc3RyaWN0IDIgb3IgZGlzdHJpY3QgNS4gCgpgbXV0YXRlYCBhZGRzIGEgdmFyaWFibGUgdGhhdCBjb2RlcyBhbmQgbGFiZWxzIHRoZSBkYXlzIG9mIHRoZSB3ZWVrIGZvciBlYWNoIGNyaW1lIHRoYXQgb2NjdXJyZWQsIGFuZCBjcmVhdGVzIGFub3RoZXIgdGltZSBvZiBkYXkgdmFyaWFibGUgCgpgYGB7ciBDcmVhdGVzIDIwMTkgQ2F0ZWdvcml6ZWQgVGlkeSBDcmltZSBGaWxlfQp0aWR5Q3JpbWVzMTkgPC0gY3JpbWVzMTkgJT4lIAogIGNzX2ZpbHRlcl9jb3VudCguLCB2YXIgPSBjb3VudCkgJT4lCiAgY3NfZmlsdGVyX2NyaW1lKC4sIHZhciA9IGNyaW1lLCAicGFydCAxIikgJT4lCiAgY3NfY3JpbWVfY2F0KC4sIHZhciA9IGNyaW1lLCBjcmltZUNhdE51bSwgIm51bWVyaWMiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TmFtZSwgInN0cmluZyIpICU+JQogIGNzX2NyaW1lKC4sIHZhciA9IGNyaW1lLCB2aW9sZW50LCAidmlvbGVudCIpICU+JQogIGNzX2NyaW1lKC4sIHZhciA9IGNyaW1lLCBwcm9wZXJ0eSwgInByb3BlcnR5IikgJT4lCiAgY3NfcGFyc2VfZGF0ZSguLCBkYXRlX29jY3VyLCBkYXRlVmFyID0gZGF0ZU9jYywgdGltZVZhciA9IHRpbWVPY2MpICU+JQogIGZpbHRlcihkYXRlT2NjID49IGFzLkRhdGUoIjIwMTktMDgtMDEiKSkgJT4lCiAgZmlsdGVyKGRpc3RyaWN0ID09IDIgfCBkaXN0cmljdCA9PSA1KSAlPiUKICBtdXRhdGUod2Vla2RheSA9IHdkYXkoZGF0ZU9jYywgbGFiZWwgPSBUUlVFKSkgJT4lCiAgbXV0YXRlKHRvZCA9IHRpbWVPY2MpCgp0aWR5Q3JpbWVzMTkkbmVpZ2hib3Job29kIDwtIGFzLm51bWVyaWModGlkeUNyaW1lczE5JG5laWdoYm9yaG9vZCkKYGBgCgpgc3RycHRpbWVgIGFuZCBgZm9ybWF0YCB0YWtlcyB0aGUgbmV3IHRpbWUgdmFyaWFibGUgYW5kIGZvcm1hdHMgaXQgdG8gYSBjaGFyYWN0ZXIgc28gdGhhdCB3ZSBjYW4gZGV0ZXJtaW5lIGlmIHRoZSBjcmltZSBvY2N1cmVkIGF0IGRheSBvciBhdCBuaWdodCwgYW5kIGNyZWF0ZXMgYSBzZWNvbmQgY29kZWQgdmFyaWFibGUgdGhhdCBsYWJlbHMgZWFjaCBvYnNlcnZhdGlvbnMgYXMgZGF5IG9yIG5pZ2h0IGJhc2VkIG9uIHRoZSBuZXdseSBmb3JtYXRlZCB0aW1lIHZhcmlhYmxlLiAKCmBzZWxlY3RgIGRyb3BzIHRoZSB1bm5lZWRlZCB2YXJpYWJsZXMuIAoKYGNzX21pc3NpbmdfWFlgIGRldGVybWluZXMgd2hhdCBkYXRhIGRvZXMgbm90IGhhdmUgeCAmIHkgY29vcmRpbmF0ZXMsIGFuZCB0aGVyZWZvcmUgY2Fubm90IGJlIGFjY3VyYXRlbHkgbWFwcGVkLiAKCmBjc19yZXBsYWNlMGAgcmVwbGFjZXMgbWlzc2luZyB4ICYgeSBjb29yZGluYXRlcyB3aXRoIGBOQWAsIGFuZCBkcm9wcyB0aGUgbWlzc2luZyBkYXRhLiAKCmBgYHtyIENsZWFucyAyMDE5IFRpbWUgRGF0YSAmIE1pc3NpbmcgU3BhdGlhbCBEYXRhfQp0aWR5Q3JpbWVzMTkkdG9kIDwtIHN0cnB0aW1lKHRpZHlDcmltZXMxOSR0b2QsIHR6ID0gIkFtZXJpY2EvQ2hpY2FnbyIsICIlSDolTSIpCnRpZHlDcmltZXMxOSR0b2QgPC0gZm9ybWF0KHRpZHlDcmltZXMxOSR0b2QsIGZvcm1hdCA9ICIlSCVNJVMiKQoKdGlkeUNyaW1lczE5IDwtIHRpZHlDcmltZXMxOSAlPiUKICBtdXRhdGUoLiwgZGF5TmlnaHQgPSBpZmVsc2UodG9kID49ICIxODAwMDAiICYgdG9kIDwgIjYwMDAwMCIsICJOaWdodCIsICJEYXkiKSkgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWRhdGVUaW1lLCAtdG9kLCAtZmxhZ19jcmltZSwgLWZsYWdfYWRtaW5pc3RyYXRpdmUsIC1mbGFnX3VuZm91bmRlZCwgLWZsYWdfY2xlYW51cCkKCnRpZHlDcmltZXMxOSA8LSBjc19taXNzaW5nWFkodGlkeUNyaW1lczE5LCB2YXJYID0geF9jb29yZCwgdmFyWSA9IHlfY29vcmQsIG5ld1ZhciA9IG1pc3NpbmcpCnRhYmxlKHRpZHlDcmltZXMxOSRtaXNzaW5nKQoKdGlkeUNyaW1lczE5IDwtIHRpZHlDcmltZXMxOSAlPiUgCiAgY3NfcmVwbGFjZTAoLiwgdmFyID0geF9jb29yZCkgJT4lCiAgY3NfcmVwbGFjZTAoLiwgdmFyID0geV9jb29yZCkgJT4lIAogIGZpbHRlciguLCBtaXNzaW5nID09IEZBTFNFKSAKYGBgCgojIyBUb3RhbCBDcmltZXMgMjAxOSAtIENsZWFuCgpgYGB7cn0KdG90YWxZZWFybHlDcmltZXMxOSA8LSBjc19jb2xsYXBzZSh5ZWFyTGlzdDE5KQoKdGlkeVRvdGFsQ3JpbWVzMTkgPC0gdG90YWxZZWFybHlDcmltZXMxOSAlPiUgCiAgY3NfZmlsdGVyX2NvdW50KC4sIHZhciA9IGNvdW50KSAlPiUKICBjc19maWx0ZXJfY3JpbWUoLiwgdmFyID0gY3JpbWUsICJwYXJ0IDEiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TnVtLCAibnVtZXJpYyIpICU+JQogIGNzX2NyaW1lX2NhdCguLCB2YXIgPSBjcmltZSwgY3JpbWVDYXROYW1lLCAic3RyaW5nIikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHZpb2xlbnQsICJ2aW9sZW50IikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHByb3BlcnR5LCAicHJvcGVydHkiKSAlPiUKICBjc19wYXJzZV9tb250aCguLCB2YXIgPSBjb2RlZF9tb250aCwgeWVhclZhciA9IHJlcG9ydFllYXIsIG1vbnRoID0gbW9udGhWYXIpICU+JQogIGNzX3BhcnNlX2RhdGUoLiwgZGF0ZV9vY2N1ciwgZGF0ZVZhciA9IGRhdGVPY2MsIHRpbWVWYXIgPSB0aW1lT2NjKSAlPiUKICBmaWx0ZXIoZGlzdHJpY3QgPT0gMiB8IGRpc3RyaWN0ID09IDUpICU+JQogIG11dGF0ZSh3ZWVrZGF5ID0gd2RheShkYXRlT2NjLCBsYWJlbCA9IFRSVUUpKSAlPiUKICBtdXRhdGUodG9kID0gdGltZU9jYykgCgp0aWR5VG90YWxDcmltZXMxOSRuZWlnaGJvcmhvb2QgPC0gYXMubnVtZXJpYyh0aWR5VG90YWxDcmltZXMxOSRuZWlnaGJvcmhvb2QpCgp0aWR5VG90YWxDcmltZXMxOSR0b2QgPC0gc3RycHRpbWUodGlkeVRvdGFsQ3JpbWVzMTkkdG9kLCB0eiA9ICJBbWVyaWNhL0NoaWNhZ28iLCAiJUg6JU0iKQp0aWR5VG90YWxDcmltZXMxOSR0b2QgPC0gZm9ybWF0KHRpZHlUb3RhbENyaW1lczE5JHRvZCwgZm9ybWF0ID0gIiVIJU0lUyIpCgp0aWR5VG90YWxDcmltZXMxOSA8LSB0aWR5VG90YWxDcmltZXMxOSAlPiUKICBtdXRhdGUoLiwgZGF5TmlnaHQgPSBpZmVsc2UodG9kID49ICIxODAwMDAiICYgdG9kIDwgIjYwMDAwMCIsICJOaWdodCIsICJEYXkiKSkgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWRhdGVUaW1lLCAtdG9kLCAtZmxhZ19jcmltZSwgLWZsYWdfYWRtaW5pc3RyYXRpdmUsIC1mbGFnX3VuZm91bmRlZCwgLWZsYWdfY2xlYW51cCkKCnRpZHlUb3RhbENyaW1lczE5IDwtIGNzX21pc3NpbmdYWSh0aWR5VG90YWxDcmltZXMxOSwgdmFyWCA9IHhfY29vcmQsIHZhclkgPSB5X2Nvb3JkLCBuZXdWYXIgPSBtaXNzaW5nKQp0YWJsZSh0aWR5VG90YWxDcmltZXMxOSRtaXNzaW5nKQoKdGlkeVRvdGFsQ3JpbWVzMTkgPC0gdGlkeVRvdGFsQ3JpbWVzMTkgJT4lIAogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHhfY29vcmQpICU+JQogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHlfY29vcmQpICU+JSAKICBmaWx0ZXIoLiwgbWlzc2luZyA9PSBGQUxTRSkKCnJtKHRvdGFsQ3JpbWVzMTgpCmBgYAoKCiMjIyBHZXQgRGF0YSAtIDIwMTgKCmBgYHtyIERvd25sb2FkIDIwMTggRGF0YX0KeWVhckxpc3QxOCA8LSBjc19nZXRfZGF0YSh5ZWFyID0gMjAxOCwgaW5kZXggPSBpKQpgYGAKCiMjIyBEYXRhIFByZXBlcmF0aW9uCgpgYGB7ciBWYWxpZGF0ZSAyMDE4IERhdGF9CmNzX3ZhbGlkYXRlKHllYXJMaXN0MTgsIHllYXIgPSAyMDE4KQpgYGAKCiMjIyBEb3dubG9hZCBMYXN0IFllYXIncyBNb250aApgYGB7ciBFeHRyYWN0IExhc3QgWWVhcnMgQ3JpbWUgRGF0YSBGb3IgQ3VycmVudCBNb250aH0KdG90YWxDcmltZXMxOCA8LSBjc19jb2xsYXBzZSh5ZWFyTGlzdDE4KQptb250aENyaW1lczE4IDwtIGNzX2V4dHJhY3RfbW9udGgoeWVhckxpc3QxOCwgbW9udGggPSAiQXVndXN0IikKcm0oeWVhckxpc3QxOCkKYGBgCgojIyMgQ2xlYW4gJiBDYXRlZ29yaXplIERhdGEgLSAyMDE4CgpgYGB7ciBGaWx0ZXIgJiBDYXRlZ29yaXplIDIwMTggRGF0YSBmb3IgQ3VycmVudCBNb250aH0KdGlkeU1vbnRoQ3JpbWVzMTggPC0gbW9udGhDcmltZXMxOCAlPiUgCiAgY3NfZmlsdGVyX2NvdW50KC4sIHZhciA9IGNvdW50KSAlPiUKICBjc19maWx0ZXJfY3JpbWUoLiwgdmFyID0gY3JpbWUsICJwYXJ0IDEiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TnVtLCAibnVtZXJpYyIpICU+JQogIGNzX2NyaW1lX2NhdCguLCB2YXIgPSBjcmltZSwgY3JpbWVDYXROYW1lLCAic3RyaW5nIikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHZpb2xlbnQsICJ2aW9sZW50IikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHByb3BlcnR5LCAicHJvcGVydHkiKSAlPiUKICBjc19wYXJzZV9kYXRlKC4sIGRhdGVfb2NjdXIsIGRhdGVWYXIgPSBkYXRlT2NjLCB0aW1lVmFyID0gdGltZU9jYykgJT4lCiAgZmlsdGVyKGRhdGVPY2MgPj0gYXMuRGF0ZSgiMjAxOC0wOC0wMSIpICYgZGF0ZU9jYyA8PSBhcy5EYXRlKCIyMDE4LTA4LTMxIikpICU+JQogIGZpbHRlcihkaXN0cmljdCA9PSAyIHwgZGlzdHJpY3QgPT0gNSkgJT4lCiAgbXV0YXRlKHdlZWtkYXkgPSB3ZGF5KGRhdGVPY2MsIGxhYmVsID0gVFJVRSkpICU+JQogIG11dGF0ZSh0b2QgPSB0aW1lT2NjKQoKdGlkeU1vbnRoQ3JpbWVzMTgkbmVpZ2hib3Job29kIDwtIGFzLm51bWVyaWModGlkeU1vbnRoQ3JpbWVzMTgkbmVpZ2hib3Job29kKQoKdGlkeU1vbnRoQ3JpbWVzMTgkdG9kIDwtIHN0cnB0aW1lKHRpZHlNb250aENyaW1lczE4JHRvZCwgdHogPSAiQW1lcmljYS9DaGljYWdvIiwgIiVIOiVNIikKdGlkeU1vbnRoQ3JpbWVzMTgkdG9kIDwtIGZvcm1hdCh0aWR5TW9udGhDcmltZXMxOCR0b2QsIGZvcm1hdCA9ICIlSCVNJVMiKQoKdGlkeU1vbnRoQ3JpbWVzMTggPC0gdGlkeU1vbnRoQ3JpbWVzMTggJT4lCiAgbXV0YXRlKC4sIGRheU5pZ2h0ID0gaWZlbHNlKHRvZCA+PSAiMTgwMDAwIiAmIHRvZCA8ICI2MDAwMDAiLCAiTmlnaHQiLCAiRGF5IikpICU+JSAKICBkcGx5cjo6c2VsZWN0KC1kYXRlVGltZSwgLXRvZCwgLWZsYWdfY3JpbWUsIC1mbGFnX2FkbWluaXN0cmF0aXZlLCAtZmxhZ191bmZvdW5kZWQsIC1mbGFnX2NsZWFudXApCgp0aWR5TW9udGhDcmltZXMxOCA8LSBjc19taXNzaW5nWFkodGlkeU1vbnRoQ3JpbWVzMTgsIHZhclggPSB4X2Nvb3JkLCB2YXJZID0geV9jb29yZCwgbmV3VmFyID0gbWlzc2luZykKdGFibGUodGlkeU1vbnRoQ3JpbWVzMTgkbWlzc2luZykKCnRpZHlNb250aENyaW1lczE4IDwtIHRpZHlNb250aENyaW1lczE4ICU+JSAKICBjc19yZXBsYWNlMCguLCB2YXIgPSB4X2Nvb3JkKSAlPiUKICBjc19yZXBsYWNlMCguLCB2YXIgPSB5X2Nvb3JkKSAlPiUgCiAgZmlsdGVyKC4sIG1pc3NpbmcgPT0gRkFMU0UpCmBgYAoKYGBge3IgVG90YWwgQ3JpbWVzIGZvciAyMDE4IFRpZGllZH0KdGlkeVRvdGFsQ3JpbWVzMTggPC0gdG90YWxDcmltZXMxOCAlPiUgCiAgY3NfZmlsdGVyX2NvdW50KC4sIHZhciA9IGNvdW50KSAlPiUKICBjc19maWx0ZXJfY3JpbWUoLiwgdmFyID0gY3JpbWUsICJwYXJ0IDEiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TnVtLCAibnVtZXJpYyIpICU+JQogIGNzX2NyaW1lX2NhdCguLCB2YXIgPSBjcmltZSwgY3JpbWVDYXROYW1lLCAic3RyaW5nIikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHZpb2xlbnQsICJ2aW9sZW50IikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHByb3BlcnR5LCAicHJvcGVydHkiKSAlPiUKICBjc19wYXJzZV9tb250aCguLCB2YXIgPSBjb2RlZF9tb250aCwgeWVhclZhciA9IHJlcG9ydFllYXIsIG1vbnRoID0gbW9udGhWYXIpICU+JQogIGNzX3BhcnNlX2RhdGUoLiwgZGF0ZV9vY2N1ciwgZGF0ZVZhciA9IGRhdGVPY2MsIHRpbWVWYXIgPSB0aW1lT2NjKSAlPiUKICBmaWx0ZXIoZGlzdHJpY3QgPT0gMiB8IGRpc3RyaWN0ID09IDUpICU+JQogIG11dGF0ZSh3ZWVrZGF5ID0gd2RheShkYXRlT2NjLCBsYWJlbCA9IFRSVUUpKSAlPiUKICBtdXRhdGUodG9kID0gdGltZU9jYykgCgp0aWR5VG90YWxDcmltZXMxOCRuZWlnaGJvcmhvb2QgPC0gYXMubnVtZXJpYyh0aWR5VG90YWxDcmltZXMxOCRuZWlnaGJvcmhvb2QpCgp0aWR5VG90YWxDcmltZXMxOCR0b2QgPC0gc3RycHRpbWUodGlkeVRvdGFsQ3JpbWVzMTgkdG9kLCB0eiA9ICJBbWVyaWNhL0NoaWNhZ28iLCAiJUg6JU0iKQp0aWR5VG90YWxDcmltZXMxOCR0b2QgPC0gZm9ybWF0KHRpZHlUb3RhbENyaW1lczE4JHRvZCwgZm9ybWF0ID0gIiVIJU0lUyIpCgp0aWR5VG90YWxDcmltZXMxOCA8LSB0aWR5VG90YWxDcmltZXMxOCAlPiUKICBtdXRhdGUoLiwgZGF5TmlnaHQgPSBpZmVsc2UodG9kID49ICIxODAwMDAiICYgdG9kIDwgIjYwMDAwMCIsICJOaWdodCIsICJEYXkiKSkgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWRhdGVUaW1lLCAtdG9kLCAtZmxhZ19jcmltZSwgLWZsYWdfYWRtaW5pc3RyYXRpdmUsIC1mbGFnX3VuZm91bmRlZCwgLWZsYWdfY2xlYW51cCkKCnRpZHlUb3RhbENyaW1lczE4IDwtIGNzX21pc3NpbmdYWSh0aWR5VG90YWxDcmltZXMxOCwgdmFyWCA9IHhfY29vcmQsIHZhclkgPSB5X2Nvb3JkLCBuZXdWYXIgPSBtaXNzaW5nKQp0YWJsZSh0aWR5VG90YWxDcmltZXMxOCRtaXNzaW5nKQoKdGlkeVRvdGFsQ3JpbWVzMTggPC0gdGlkeVRvdGFsQ3JpbWVzMTggJT4lIAogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHhfY29vcmQpICU+JQogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHlfY29vcmQpICU+JSAKICBmaWx0ZXIoLiwgbWlzc2luZyA9PSBGQUxTRSkKCnJtKHRvdGFsQ3JpbWVzMTgpCmBgYAoKCiMjIyBDb21iaW5lIDIwMTggJiAyMDE5IAoKYGBge3IgSm9pbiBQcmV2aW91cyBZZWFycyBDcmltZXN9CmF1Z3VzdENyaW1lcyA8LSByYmluZCh0aWR5TW9udGhDcmltZXMxOCwgdGlkeUNyaW1lczE5KQpgYGAKCiMjIyBDcmVhdGUgU3BhdGlhbCBPYmplY3RzCgpgYGB7ciBDcmVhdGUgU0Ygb2JqZWN0cyBmb3IgMjAxOCAmIDIwMTkgQ3JpbWVzfQpjcmltZXNZZWFyMThfc2YgPC0gY3NfcHJvamVjdFhZKHRpZHlUb3RhbENyaW1lczE4LCB2YXJYID0geF9jb29yZCwgdmFyWSA9IHlfY29vcmQsIGNycyA9IDEwMjY5NikKY3JpbWVzMTlfc2YgPC0gY3NfcHJvamVjdFhZKHRpZHlDcmltZXMxOSwgdmFyWCA9IHhfY29vcmQsIHZhclkgPSB5X2Nvb3JkLCBjcnMgPSAxMDI2OTYpCmF1Z3VzdENyaW1lc19zZiA8LSBjc19wcm9qZWN0WFkoYXVndXN0Q3JpbWVzLCB2YXJYID0geF9jb29yZCwgdmFyWSA9IHlfY29vcmQsIGNycyA9IDEwMjY5NikKYGBgCgojIyMgUHJlcCBmb3IgRGF0YSBieSBOZWlnaGJvcmhvb2QKCmBgYHtyIE5laWdoYm9yaG9vZCBOdW1iZXIgTGlzdHN9CnNhIDwtIGMoMzksMjgsMzgsNTEsNTMsNTQsNTgsNDYsNDcsNDgsNDgpCmRzdDIgPC0gYyg3OjE1LDI3OjI5LCAzOTo0NSw4MSw4Miw4Nyw4OCkKZHN0NSA8LSBjKDM4LDQ2OjU4LDc4KQpgYGAKCiMjIE1hcHBpbmcgCgpPbmUgd2F5IHdlIHdvcmsgdG8gaW1wcm92ZSB0aGUgbGV2ZWwgb2YgcGh5c2ljYWwgJiBwZXJzb25hbCBzZWN1cml0eSBpcyB0aGUgYW5hbHlzaXMgYW5kIGRpc3RyaWJ1dGlvbiBvZiBjcmltZSBkYXRhIGFuZCBzdGF0aXN0aWNzLiBUaGUgb3JpZ2luYWwgc291cmNlIG9mIHRoaXMgY3JpbWUgZGF0YSBpcyA8aHR0cDovL3NsbXBkLm9yZy9jcmltZXJlcG9ydHMuc2h0bWw+LiBUaGlzIG5vdGVib29rIHRha2VzIHRoZSBkYXRhIHRoYXQgd2FzIHByZXZpb3VzbHkgY2xlYW5lZCBhbmQgbWFwcyB0aGUgZGF0YS4gIAoKIyMgTG9hZCBTcGF0aWFsIERhdGEgCgojIyMgQ29vcmRpbmF0ZXMKCmBgYHtyIFNlcnZpY2UgQXJlYSBOZWlnaGJvcmhvb2QgQ29vcmRpbmF0ZXN9Cnh5ZnBzZSA8LSBjKC05MC4yNjc5LCAtOTAuMjQyMywgMzguNjE3NiwgMzguNjMzNCkKeHljd2UgPC0gYygtOTAuMjc1OSwgLTkwLjIzNjgsIDM4LjYyODYsIDM4LjY1NTIpCnh5Ym90IDwtIGMoLTkwLjI2MTksIC05MC4yNDA5LCAzOC42MTY1LCAzOC42Mjk2KQp4eWRicCA8LSBjKC05MC4yODY5LCAtOTAuMjcyNiwgMzguNjQzMywgMzguNjU2NikKeHlzZGIgPC0gYygtOTAuMzAyNiwgLTkwLjI4MjcsIDM4LjY0NTYsIDM4LjY1NzEpCnh5d2UgPC0gYygtOTAuMzAyMCwgLTkwLjI3MTIsIDM4LjY1MTcsIDM4LjY3MTApCnh5dnAgPC0gYygtOTAuMjgwMywgLTkwLjI3MTIsIDM4LjY1MTcsIDM4LjY2MjIpCnh5YWMgPC0gYygtOTAuMjc0NCwgLTkwLjI2MDksIDM4LjY1MDUsIDM4LjY2NjEpCnh5ZnAgPC0gYygtOTAuMjY0OCwgLTkwLjI1NDMsIDM4LjY0OTMsIDM4LjY2NTUpCnh5bHAgPC0gYygtOTAuMjU4OCwgLTkwLjI0MzcsIDM4LjY0ODEsIDM4LjY2MjQpCnh5dmQgPC0gYygtOTAuMjUyMCwgLTkwLjIzMDQsIDM4LjY0MjYsIDM4LjY1ODUpCnh5bWMgPC0gYygtOTAuMjY3OCwgLTkwLjI1MTUsIDM4LjYzMDUsIDM4LjY0MTEpCnh5Y3R4IDwtIGMoLTkwLjI1ODEsIC05MC4yNDE5LCAzOC42Mjk5LCAzOC42Mzg2KQp4eWdydiA8LSBjKC05MC4yNjYyLCAtOTAuMjQ0MCwgMzguNjIzOCwgMzguNjMxOCkKeHlkc3QyIDwtIGMoLTkwLjMyMDMsIC05MC4yMjk3LCAzOC41NjEzLCAzOC42NDkzKQp4eWRzdDUgPC0gYygtOTAuMzA4MCwgLTkwLjIxMzIsIDM4LjYyNzMsIDM4LjY5NjIpCmBgYAoKCiMjIyBPcGVuIFN0cmVldCBNYXAgZnJvbSBNYXBib3ggLSBCYXNlbWFwIFRpbGUgSW1hZ2VyeQoKYGBge3IgT2J0YWluIEJhc2VtYXAgVGlsZXMsIGluY2x1ZGU9RkFMU0V9CmZwc2VfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlmcHNlKSAlPiUKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpjd2VfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHljd2UpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpib3RfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlib3QpICU+JQogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCmRicF90aWxlcyA8LSByYXN0ZXI6OmV4dGVudCh4eWRicCkgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCnNkYl90aWxlcyA8LSByYXN0ZXI6OmV4dGVudCh4eXNkYikgJT4lCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKd2VfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHl3ZSkgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCnZwX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5dnApICU+JQogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCmFjX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5YWMpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpmcF90aWxlcyA8LSByYXN0ZXI6OmV4dGVudCh4eWZwKSAlPiUgCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKbHBfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlscCkgJT4lCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKdmRfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHl2ZCkgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCm1jX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5bWMpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpjdHhfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHljdHgpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpncnZfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlncnYpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpkc3QyX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5ZHN0MikgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCmRzdDVfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlkc3Q1KSAlPiUgCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKcm0oeHlmcHNlLCB4eWN3ZSwgeHlib3QsIHh5ZGJwLCB4eXNkYiwgeHl3ZSwgeHl2cCwgeHlhYywgeHlmcCwgeHlscCwgeHl2ZCwgeHltYywgeHljdHgsIHh5Z3J2LCB4eWRzdDIsIHh5ZHN0NSkKYGBgCgojIyMgTG9hZCBFeHRlcm5hbCBEYXRhCgojIyMjIFBvcHVsYXRpb24gRGF0YSAKCmBgYHtyfQpsb2FkKGhlcmUoImRhdGEvbmJoZF9wb3AxMC5yZGEiKSkKYGBgCgoKIyMjIyBTcGF0aWFsIAoKYGBge3IgbG9hZCBzaGFwZWZpbGVzLCBpbmNsdWRlPUZBTFNFfQpzdF9yZWFkKGhlcmUoImRhdGEiLCAiZXh0ZXJuYWwiLCAibWVkLWNhbXB1cyIsICJtZWRjYW1wdXMuc2hwIikpICU+JQogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpIC0+IG1lZF9jYW1wdXMKCnN0X3JlYWQoaGVyZSgiZGF0YSIsICJleHRlcm5hbCIsICJjb3J0ZXgtYm91bmRhcnkiLCAiQ09SVEVYIEJPVU5EQVJZLnNocCIpKSAlPiUKICBzdF90cmFuc2Zvcm0oY3JzID0gMTAyNjk2KSAtPiBjb3J0ZXgKCnN0X3JlYWQoaGVyZSgiZGF0YSIsICJleHRlcm5hbCIsICJncm92ZS1jaWQiLCAiZ3JvdmVjaWQuc2hwIikpICU+JQogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpIC0+IGdyb3ZlX2NpZAoKc3RfcmVhZChoZXJlKCJkYXRhIiwgImV4dGVybmFsIiwgInN0bF9uZWlnaGJvcmhvb2RzIiwgIm5iaGRzLnNocCIpKSAlPiUKICBzdF90cmFuc2Zvcm0oY3JzID0gMTAyNjk2KSAlPiUgCiAgcmVuYW1lKC4sICJuZWlnaGJvcmhvb2QiID0gTkhEX05VTSktPiBuaG9vZHNfc2YKCmZwc2UgPC0gZmlsdGVyKG5ob29kc19zZiwgbmVpZ2hib3Job29kID09IDM5ICkKY3dlIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSAzOCApCmJvdCA8LSBmaWx0ZXIobmhvb2RzX3NmLCBuZWlnaGJvcmhvb2QgPT0gMjggKQpkYnAgPC0gZmlsdGVyKG5ob29kc19zZiwgbmVpZ2hib3Job29kID09IDQ3ICkKc2RiIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA0NiApCndlIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA0OCApCnZwIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA0OSApCmFjIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1MSApCmZwIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1MyApCmxwIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1NCApCnZkIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1OCApCmBgYAoKIyMjIENvbWJpbmUgUG9wdWxhdGlvbiAmIE5laWdoYm9yaG9vZCBTcGF0aWFsIERhdGEgYnkgUG9saWNlIERpc3RyaWN0CgojIyMjIE9nYW5pemUgJiBGaWx0ZXIgQ3JpbWUgRGF0YSBieSBOZWlnaGJvcmhvb2QgCgpgYGB7ciBDcmltZSBSYXRlcyAtIERpc3RyaWN0IDJ9CmRzdF8yIDwtIHRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCAlaW4lIGRzdDIpICU+JSAKICBncm91cF9ieSguLCBuZWlnaGJvcmhvb2QpICU+JQogIGNvdW50KCkgJT4lIAogIHJlbmFtZShjcmltZVRvdGFsID0gbikgJT4lCiAgbGVmdF9qb2luKG5iaGRfcG9wMTAsIGJ5ID0gIm5laWdoYm9yaG9vZCIpICU+JSAKICBtdXRhdGUoLiwgY3JpbWVSYXRlID0gKGNyaW1lVG90YWwvcG9wMTApKjEwMDApICU+JSAKICBkcm9wX25hKCkKYGBgCgpgYGB7ciBDcmltZSBSYXRlcyAtIERpc3RyaWN0IDV9CmRzdF81IDwtIHRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCAlaW4lIGRzdDUpICU+JSAKICBncm91cF9ieSguLCBuZWlnaGJvcmhvb2QpICU+JQogIGNvdW50KCkgJT4lIAogIHJlbmFtZShjcmltZVRvdGFsID0gbikgJT4lCiAgbGVmdF9qb2luKG5iaGRfcG9wMTAsIGJ5ID0gIm5laWdoYm9yaG9vZCIpICU+JSAKICBtdXRhdGUoLiwgY3JpbWVSYXRlID0gKGNyaW1lVG90YWwvcG9wMTApKjEwMDApICU+JSAKICBkcm9wX25hKCkKYGBgCgpgYGB7ciBKb2luIFJhdGVzICYgTmVpZ2hib3Job29kcyAtIERpc3RyaWN0IDJ9CmRzdF8yX3BvcCA8LSBsZWZ0X2pvaW4obmhvb2RzX3NmLCBkc3RfMiwgYnkgPSAibmVpZ2hib3Job29kIikgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpICU+JQogIGRyb3BfbmEoKSAlPiUgCiAgc3Vic2V0KC4sIG5laWdoYm9yaG9vZCAhPSA4OCkKYGBgCgpgYGB7ciBKb2luIFJhdGVzICYgTmVpZ2hib3Job29kcyAtIERpc3RyaWN0IDV9CmRzdF81X3BvcCA8LSBsZWZ0X2pvaW4obmhvb2RzX3NmLCBkc3RfNSwgYnkgPSAibmVpZ2hib3Job29kIikgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpICU+JQogIGRyb3BfbmEoKQpgYGAKCgojIyMgRlBTRSwgQk9ULCBDV0UsIE1DIAoKIyMjIyBNYXAgQ3JlYXRpb24KCiMjIyMjIEZQU0UKCmBgYHtyIEZQU0UgVG90YWwgQ3JpbWV9CmZwc2VfdG90YWxfdG0gPC0gdG1fc2hhcGUoZnBzZV90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAyLCAKICAgICAgICAgICAgICAgbHR5ID0gImRhc2hlZCIpICsKICBmaWx0ZXIoY3JpbWVzMTlfc2YsIAogICAgICAgICBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JQogIHRtX3NoYXBlKCkgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImNyaW1lQ2F0TmFtZSIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlNldDEiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlBhcnQgMSBDcmltZXMiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJGUFNFIFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpmcHNlX3RvdGFsX3RtCmBgYCAKCgpgYGB7ciBGUFNFIERheSAmIE5pZ2h0fQpmcHNlX2RuX3RtIDwtIHRtX3NoYXBlKGZwc2VfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2ZpbGwoY29sID0gIiM5ZWNhZTEiLCAKICAgICAgICAgICAgYWxwaGEgPSAuNSkgKwogICAgdG1fYm9yZGVycyhjb2wgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgbHdkID0gMiwgCiAgICAgICAgICAgICAgIGx0eSA9ICJkYXNoZWQiKSArCiAgZmlsdGVyKGNyaW1lczE5X3NmLCAKICAgICAgICAgbmVpZ2hib3Job29kID09IDM5KSAlPiUKICB0bV9zaGFwZSgpICsKICAgIHRtX2J1YmJsZXMoc2l6ZSA9IC4yNSwgCiAgICAgICAgICAgICAgIGNvbCA9ICJkYXlOaWdodCIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIi1SZEJ1IiwgCiAgICAgICAgICAgICAgIHRpdGxlLmNvbCA9ICJUaW1lIG9mIENyaW1lcyIpICsKICB0bV9jcmVkaXRzKCLCqSBNYXBib3gsIMKpIE9wZW5TdHJlZXRNYXAiLCBwb3NpdGlvbiA9IGMoImxlZnQiLCAiQk9UVE9NIikpICsKICB0bV9sYXlvdXQoCiAgICBtYWluLnRpdGxlID0gIkZQU0UgVGltZSBvZiBDcmltZXMgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmZwc2VfZG5fdG0KYGBgCgpgYGB7ciBGUFNFIENyaW1lcyBBZ2FpbnN0IFBlcnNvbnN9CmZwc2VfdmxudF90bSA8LSB0bV9zaGFwZShmcHNlX3RpbGVzKSArCiAgdG1fcmdiKCkgKwogIG5ob29kc19zZiAlPiUKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgdG1fc2hhcGUoKSArCiAgICB0bV9maWxsKGNvbCA9ICIjOWVjYWUxIiwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIGZpbHRlcihjcmltZXMxOV9zZiwgCiAgICAgICAgIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lCiAgdG1fc2hhcGUoKSArCiAgICB0bV9idWJibGVzKHNpemUgPSAuMjUsIAogICAgICAgICAgICAgICBjb2wgPSAidmlvbGVudCIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlJlZHMiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlZpb2xlbnQiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJGUFNFIFZpb2xlbnQgQ3JpbWUgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmZwc2VfdmxudF90bQpgYGAKCmBgYHtyIEZQU0UgRGVuc2l0eSBNYXAgU0Z9CmNyaW1lczE5X3NmICU+JQogIGZpbHRlcihuZWlnaGJvcmhvb2QgPT0gMzkpICU+JQogIHNtb290aF9tYXAoLiwgYmFuZHdpZHRoID0gMC41LCBzdHlsZSA9ICJwcmV0dHkiLAogIGNvdmVyID0gZnBzZSkgLT4gZnBzZV9kZW5zaXRpZXMKYGBgCgoKYGBge3IgRlBTRSBEZW5zaXR5IE1hcCBPdXRwdXR9CmZwc2VfZGVuX3RtIDwtIHRtX3NoYXBlKGZwc2VfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2ZpbGwoY29sID0gTkEsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAyLCAKICAgICAgICAgICAgICAgbHR5ID0gImRhc2hlZCIpICsKICB0bV9zaGFwZShmcHNlX2RlbnNpdGllcyRwb2x5Z29ucykgKwogIHRtX2ZpbGwoY29sID0gImxldmVsIiwgcGFsZXR0ZSA9ICJCdVB1IiwgYWxwaGEgPSAuNjAsIAogICAgdGl0bGUgPSBleHByZXNzaW9uKCJDcmltZXMgcGVyICIgKiBrbV4yKSkgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiRlBTRSBDcmltZSBEZW5zaXR5IC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpmcHNlX2Rlbl90bQpgYGAKIyMjIyMjIEdyb3ZlIENJRCAKCmBgYHtyIEdyb3ZlIENJRCBUb3RhbCBDcmltZX0KZ3JvdmVfY3JpbWVzIDwtIHN0X2ludGVyc2VjdGlvbihjcmltZXMxOV9zZiwgZ3JvdmVfY2lkKQoKZnBzZV9ncm92ZV90bSA8LSB0bV9zaGFwZShncnZfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIHRtX3NoYXBlKGdyb3ZlX2NpZCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAxLCAKICAgICAgICAgICAgICAgbHR5ID0gInNvbGlkIikgKwogIHRtX3NoYXBlKGdyb3ZlX2NyaW1lcykgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImNyaW1lQ2F0TmFtZSIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlNldDEiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlBhcnQgMSBDcmltZXMiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJHcm92ZSBDSUQgVG90YWwgQ3JpbWUgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmZwc2VfZ3JvdmVfdG0KYGBgCgojIyMjIyBDV0UKCgpgYGB7ciBDV0UgVG90YWwgQ3JpbWV9CmN3ZV90b3RhbF90bSA8LSB0bV9zaGFwZShjd2VfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2ZpbGwoY29sID0gIiM5ZWNhZTEiLCAKICAgICAgICAgICAgYWxwaGEgPSAuNSkgKwogICAgdG1fYm9yZGVycyhjb2wgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgbHdkID0gMiwgCiAgICAgICAgICAgICAgIGx0eSA9ICJkYXNoZWQiKSArCiAgZmlsdGVyKGNyaW1lczE5X3NmLCAKICAgICAgICAgbmVpZ2hib3Job29kID09IDM4KSAlPiUKICB0bV9zaGFwZSgpICsKICAgIHRtX2J1YmJsZXMoc2l6ZSA9IC4yNSwgCiAgICAgICAgICAgICAgIGNvbCA9ICJjcmltZUNhdE5hbWUiLCAKICAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJTZXQxIiwgCiAgICAgICAgICAgICAgIHRpdGxlLmNvbCA9ICJQYXJ0IDEgQ3JpbWVzIikgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiQ1dFIFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpjd2VfdG90YWxfdG0KYGBgIAoKCmBgYHtyIGN3ZSBEYXkgJiBOaWdodH0KY3dlX2RuX3RtIDwtIHRtX3NoYXBlKGN3ZV90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAyLCAKICAgICAgICAgICAgICAgbHR5ID0gImRhc2hlZCIpICsKICBmaWx0ZXIoY3JpbWVzMTlfc2YsIAogICAgICAgICBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JQogIHRtX3NoYXBlKCkgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImRheU5pZ2h0IiwgCiAgICAgICAgICAgICAgIHBhbGV0dGUgPSAiLVJkQnUiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlRpbWUgb2YgQ3JpbWVzIikgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiQ1dFIFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpjd2VfZG5fdG0KYGBgCgpgYGB7ciBDV0UgQ3JpbWVzIEFnYWluc3QgUGVyc29uc30KY3dlX3ZsbnRfdG0gPC0gdG1fc2hhcGUoY3dlX3RpbGVzKSArCiAgdG1fcmdiKCkgKwogIG5ob29kc19zZiAlPiUKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgdG1fc2hhcGUoKSArCiAgICB0bV9maWxsKGNvbCA9ICIjOWVjYWUxIiwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIGZpbHRlcihjcmltZXMxOV9zZiwgCiAgICAgICAgIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lCiAgdG1fc2hhcGUoKSArCiAgICB0bV9idWJibGVzKHNpemUgPSAuMjUsIAogICAgICAgICAgICAgICBjb2wgPSAidmlvbGVudCIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlJlZHMiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlZpb2xlbnQiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJDV0UgVGltZSBvZiBDcmltZXMgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmN3ZV92bG50X3RtCmBgYAoKYGBge3IgQ1dFIERlbnNpdHkgTWFwIFNGfQpjd2VfZGVuc2l0aWVzIDwtIGNyaW1lczE5X3NmICU+JQogIGZpbHRlcihuZWlnaGJvcmhvb2QgPT0gMzgpICU+JQogIHNtb290aF9tYXAoLiwgYmFuZHdpZHRoID0gMC41LCBzdHlsZSA9ICJwcmV0dHkiLAogIGNvdmVyID0gY3dlKQpgYGAKCgpgYGB7ciBDV0UgRGVuc2l0eSBNYXAgT3V0cHV0fQpjd2VfZGVuX3RtIDwtIHRtX3NoYXBlKGN3ZV90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fZmlsbChjb2wgPSBOQSwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIHRtX3NoYXBlKGN3ZV9kZW5zaXRpZXMkcG9seWdvbnMpICsKICB0bV9maWxsKGNvbCA9ICJsZXZlbCIsIHBhbGV0dGUgPSAiQnVQdSIsIGFscGhhID0gLjYwLCAKICAgIHRpdGxlID0gZXhwcmVzc2lvbigiQ3JpbWVzIHBlciAiICoga21eMikpICsKICB0bV9jcmVkaXRzKCLCqSBNYXBib3gsIMKpIE9wZW5TdHJlZXRNYXAiLCBwb3NpdGlvbiA9IGMoImxlZnQiLCAiQk9UVE9NIikpICsKICB0bV9sYXlvdXQoCiAgICBtYWluLnRpdGxlID0gIkNXRSBDcmltZSBEZW5zaXR5LSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmN3ZV9kZW5fdG0KYGBgCiMjIyMjIyBNZWRpY2FsIENhbXB1cwoKYGBge3IgTWVkaWNhbCBDYW1wdXMgVG90YWwgQ3JpbWUgMjAxOX0KbWNfY3JpbWVzIDwtIHN0X2ludGVyc2VjdGlvbihjcmltZXMxOV9zZiwgbWVkX2NhbXB1cykKCgpjd2VfbWNfdG0gPC0gdG1fc2hhcGUobWNfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIHRtX3NoYXBlKG1lZF9jYW1wdXMpICsKICAgIHRtX2ZpbGwoY29sID0gIiM5ZWNhZTEiLCAKICAgICAgICAgICAgYWxwaGEgPSAuNSkgKwogICAgdG1fYm9yZGVycyhjb2wgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgbHdkID0gMSwgCiAgICAgICAgICAgICAgIGx0eSA9ICJzb2xpZCIpICsKICB0bV9zaGFwZShtY19jcmltZXMpICsKICAgIHRtX2J1YmJsZXMoc2l6ZSA9IC4yNSwgCiAgICAgICAgICAgICAgIGNvbCA9ICJjcmltZUNhdE5hbWUiLCAKICAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJTZXQxIiwgCiAgICAgICAgICAgICAgIHRpdGxlLmNvbCA9ICJQYXJ0IDEgQ3JpbWVzIikgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiTWVkLiBDYW1wdXMgVG90YWwgQ3JpbWUgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmN3ZV9tY190bQoKbWNfY3JpbWVzXzE4IDwtIHN0X2ludGVyc2VjdGlvbihjcmltZXNZZWFyMThfc2YsIG1lZF9jYW1wdXMpICU+JSAKICBhcy5kYXRhLmZyYW1lKCkKCm1jX2NyaW1lcyA8LSBtY19jcmltZXMgJT4lIAogICBhcy5kYXRhLmZyYW1lKCkKCm1jX2NyaW1lc18xOCAlPiUgCiAgZ3JvdXBfYnkobW9udGhWYXIpICU+JSAKICBjb3VudChjcmltZUNhdE5hbWUpICU+JSAKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbikgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBtb250aFZhciwgdmFsdWVzX2Zyb20gPSAiTnVtYmVyIG9mIENyaW1lcyIpICU+JSAKICByZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSAlPiUgCiAgcmVuYW1lKC4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSwgCiAgICAgICAgICJKYW51YXJ5IiA9ICIwMSIsCiAgICAgICAgICJGZWJydWFyeSIgPSAiMDIiLAogICAgICAgICAiTWFyY2giID0gIjAzIiwKICAgICAgICAgIkFwcmlsIiA9ICIwNCIsCiAgICAgICAgICJNYXkiID0gIjA1IiwKICAgICAgICAgIkp1bmUiID0gIjA2IiwKICAgICAgICAgIkp1bHkiID0gIjA3IiwKICAgICAgICAgIkF1Z3VzdCIgPSAiMDgiLAogICAgICAgICAiU2VwdGVtYmVyIiA9ICIwOSIsCiAgICAgICAgICJPY3RvYmVyIiA9ICIxMCIsCiAgICAgICAgICJOb3ZlbWJlciIgPSAiMTEiLAogICAgICAgICAiRGVjZW1iZXIiID0gIjEyIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAiY29sIiwgbmFtZSA9ICJUb3RhbCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAtPiBtY18yMDE4CgptY19jcmltZXMgJT4lIAogIGdyb3VwX2J5KGNyaW1lQ2F0TmFtZSkgJT4lIAogIGNvdW50KCkgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiUGFydCAxIENyaW1lcyIgPSBjcmltZUNhdE5hbWUpIC0+IG1jX2NyaW1lQ2F0CgprYWJsZShtY19jcmltZUNhdCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJtY19jcmltQ2F0LmpwZWciKQoKbWNfY3JpbWVzICU+JSAKICBncm91cF9ieShkYXlOaWdodCkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJUaW1lIG9mIERheSIgPSBkYXlOaWdodCkgLT4gbWNfZGF5TmlnaHQKCmthYmxlKG1jX2RheU5pZ2h0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoIm1jX2RheU5pZ2h0LmpwZWciKQoKbWNfbGFyY2VuaWVzIDwtIG1jX2NyaW1lcyAlPiUgCiAgZmlsdGVyKC4sIGNyaW1lQ2F0TnVtID09IDYpICU+JSAKICBhcy5kYXRhLmZyYW1lKCkKCgp3cml0ZS5jc3YobWNfbGFyY2VuaWVzLCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvbWNfbGFyY2VuaWVzLmNzdiIpKQoKd3JpdGUuY3N2KG1jX2NyaW1lcywgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L21jX2NyaW1lc19hdWd1c3QxOS5jc3YiKSkKd3JpdGUuY3N2KG1jXzIwMTgsIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2N3ZS8yMDE5L2F1Z3VzdC9tY19jcmltZXNfMjAxOC5jc3YiKSkKCmBgYAoKCgojIyMjIyMgQ29ydGV4CgpgYGB7ciBDb3J0ZXggVG90YWwgQ3JpbWV9CmN0eF9jcmltZXMgPC0gc3RfaW50ZXJzZWN0aW9uKGNyaW1lczE5X3NmLCBjb3J0ZXgpCgpjd2VfY3R4X3RtIDwtIHRtX3NoYXBlKGN0eF90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fYm9yZGVycyhjb2wgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgbHdkID0gMiwgCiAgICAgICAgICAgICAgIGx0eSA9ICJkYXNoZWQiKSArCiAgdG1fc2hhcGUoY29ydGV4KSArCiAgICB0bV9maWxsKGNvbCA9ICIjOWVjYWUxIiwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDEsIAogICAgICAgICAgICAgICBsdHkgPSAic29saWQiKSArCiAgdG1fc2hhcGUoY3R4X2NyaW1lcykgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImNyaW1lQ2F0TmFtZSIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlNldDEiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlBhcnQgMSBDcmltZXMiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJDb3J0ZXggVG90YWwgQ3JpbWUgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmN3ZV9jdHhfdG0KYGBgCgoKIyMjIyMgQm90YW5pY2FsIEhlaWdodHMKCmBgYHtyIEJvdGFuaWNhbCBIZWlnaHRzIFRvdGFsIENyaW1lfQpib3RfdG90YWxfdG0gPC0gdG1fc2hhcGUoYm90X3RpbGVzKSArCiAgdG1fcmdiKCkgKwogIG5ob29kc19zZiAlPiUKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDI4KSAlPiUgCiAgdG1fc2hhcGUoKSArCiAgICB0bV9maWxsKGNvbCA9ICIjOWVjYWUxIiwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIGZpbHRlcihjcmltZXMxOV9zZiwgCiAgICAgICAgIG5laWdoYm9yaG9vZCA9PSAyOCkgJT4lCiAgdG1fc2hhcGUoKSArCiAgICB0bV9idWJibGVzKHNpemUgPSAuMjUsIAogICAgICAgICAgICAgICBjb2wgPSAiY3JpbWVDYXROYW1lIiwgCiAgICAgICAgICAgICAgIHBhbGV0dGUgPSAiU2V0MSIsIAogICAgICAgICAgICAgICB0aXRsZS5jb2wgPSAiUGFydCAxIENyaW1lcyIpICsKICB0bV9jcmVkaXRzKCLCqSBNYXBib3gsIMKpIE9wZW5TdHJlZXRNYXAiLCBwb3NpdGlvbiA9IGMoImxlZnQiLCAiQk9UVE9NIikpICsKICB0bV9sYXlvdXQoCiAgICBtYWluLnRpdGxlID0gIkJvdGFuaWNhbCBIZWlnaHRzIFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpib3RfdG90YWxfdG0KYGBgCgoKIyMjIyMgRGlzdHJpY3QgMiBEZW5zaXR5IE1hcHMKYGBge3IgR2VuZXJhdGUgRGlzdHJpY3QgMiBEZW5zaXR5IE1hcHN9CmRzdDJfcmF0ZU1hcCA8LSB0bV9zaGFwZShkc3QyX3RpbGVzKSArCiAgdG1fcmdiKCkgKwogIHRtX3NoYXBlKGRzdF8yX3BvcCkgKwogIHRtX3BvbHlnb25zKGNvbCA9ICJjcmltZVJhdGUiLAogICAgICAgICAgICAgIHBhbGV0dGUgPSAiQnVQdSIsCiAgICAgICAgICAgICAgc3R5bGUgPSAiamVua3MiLAogICAgICAgICAgICAgIHRpdGxlID0gIkNyaW1lcyBwZXIgMSwwMDAgUmVzaWRlbnRzIikgKwogIHRtX3RleHQoIm5laWdoYm9yaG9vZCIsIHNoYWRvdz1UUlVFKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJEaXN0cmljdCAyIENyaW1lIFJhdGVzIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpkc3QyX3JhdGVNYXAKCgpgYGAKCmBgYHtyfQpkc3RfMl9zdGF0c1RvdGFsIDwtIGRlc2NyaWJlKGRzdF8yX3BvcCRjcmltZVRvdGFsKQpkc3RfMl9zdGF0c1JhdGUgPC0gZGVzY3JpYmUoZHN0XzJfcG9wJGNyaW1lUmF0ZSkKCmRzdF8yX3N0YXRzVG90YWwKZHN0XzJfc3RhdHNSYXRlCmBgYAoKCmBgYHtyIEdlbmVyYXRlIERpc3RyaWN0IDUgRGVuc2l0eSBNYXBzfQpkc3Q1X3JhdGVNYXAgPC0gdG1fc2hhcGUoZHN0NV90aWxlcykgKwogIHRtX3JnYigpICsKICB0bV9zaGFwZShkc3RfNV9wb3ApICsKICB0bV9wb2x5Z29ucyhjb2wgPSAiY3JpbWVSYXRlIiwKICAgICAgICAgICAgICBwYWxldHRlID0gIkJ1UHUiLAogICAgICAgICAgICAgIHN0eWxlID0gImplbmtzIiwKICAgICAgICAgICAgICB0aXRsZSA9ICJDcmltZXMgcGVyIDEsMDAwIFJlc2lkZW50cyIpICsKICB0bV90ZXh0KCJuZWlnaGJvcmhvb2QiLCBzaGFkb3c9VFJVRSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiRGlzdHJpY3QgNSBDcmltZSBSYXRlcyAtIEF1Z3VzdCAyMDE5IiwKICAgIGZyYW1lID0gRkFMU0UsCiAgICBsZWdlbmQuYmcuY29sb3IgPSAid2hpdGUiLCAKICAgIGxlZ2VuZC5mcmFtZT1UUlVFLAogICAgbGVnZW5kLm91dHNpZGUgPSBUUlVFLAogICAgbGVnZW5kLnBvc2l0aW9uID0gYygicmlnaHQiLCAiYm90dG9tIikpIAoKZHN0NV9yYXRlTWFwCmBgYApgYGB7cn0KZHN0XzVfc3RhdHNUb3RhbCA8LSBkZXNjcmliZShkc3RfNV9wb3AkY3JpbWVUb3RhbCkKZHN0XzVfc3RhdHNSYXRlIDwtIGRlc2NyaWJlKGRzdF81X3BvcCRjcmltZVJhdGUpCgpkc3RfNV9zdGF0c1RvdGFsCmRzdF81X3N0YXRzUmF0ZQpgYGAKCgojIyMgU2F2ZSBNYXBzCgpgYGB7ciBTYXZlIEZQU0UgTWFwcywgZWNobyA9IEZBTFNFLCBpbmNsdWRlID0gRkFMU0V9CnRtYXBfc2F2ZShmcHNlX3RvdGFsX3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9mcHNlLzIwMTkvYXVndXN0L2Zwc2VfdG90YWxfY3JpbWVzLmpwZWciKSwgZHBpID0gNTAwKQp0bWFwX3NhdmUoZnBzZV9kbl90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9mcHNlX2RheV9uaWdodC5qcGVnIiksIGRwaSA9IDUwMCkKdG1hcF9zYXZlKGZwc2VfdmxudF90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9mcHNlX3ZsbnQuanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShmcHNlX2Rlbl90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9mcHNlX2RlbnNpdHkuanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShmcHNlX2dyb3ZlX3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9mcHNlLzIwMTkvYXVndXN0L2Zwc2VfZ3JvdmUuanBlZyIpLCBkcGkgPSA1MDApCmBgYAoKYGBge3IgU2F2ZSBDV0UgTWFwcywgZWNobyA9IEZBTFNFLCBpbmNsdWRlID0gRkFMU0V9CnRtYXBfc2F2ZShjd2VfdG90YWxfdG0sIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2N3ZS8yMDE5L2F1Z3VzdC9jd2VfdG90YWxfY3JpbWVzLmpwZWciKSwgZHBpID0gNTAwKQp0bWFwX3NhdmUoY3dlX2RuX3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvY3dlX2RheV9uaWdodC5qcGVnIiksIGRwaSA9IDUwMCkKdG1hcF9zYXZlKGN3ZV92bG50X3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvY3dlX3ZsbnQuanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShjd2VfZGVuX3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvY3dlX2Rlbi5qcGVnIiksIGRwaSA9IDUwMCkKdG1hcF9zYXZlKGN3ZV9tY190bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L2N3ZV9tYy5qcGVnIiksIGRwaSA9IDUwMCkKdG1hcF9zYXZlKGN3ZV9jdHhfdG0sIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2N3ZS8yMDE5L2F1Z3VzdC9jd2VfY3R4LmpwZWciKSwgZHBpID0gNTAwKQpgYGAKCmBgYHtyIFNhdmUgQk9UIE1hcCwgZWNobyA9IEZBTFNFLCBpbmNsdWRlID0gRkFMU0V9CnRtYXBfc2F2ZShib3RfdG90YWxfdG0sIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2JvdC8yMDE5L2JvdF9hdWdfdG90YWwuanBlZyIpLCBkcGkgPSA1MDApCmBgYAoKYGBge3IgU2F2ZSBEaXN0cmljdCBEZW5zaXR5IE1hcHMsIGVjaG8gPSBGQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQp0bWFwX3NhdmUoZHN0Ml9yYXRlTWFwLCBmaWxlID0gaGVyZSgicmVzdWx0cy9kaXN0cmljdC0yLzIwMTkvZHN0Ml9hdWdfcmF0ZXMuanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShkc3Q1X3JhdGVNYXAsIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2Rpc3RyaWN0LTUvMjAxOS9kc3Q1X2F1Z19yYXRlcy5qcGVnIiksIGRwaSA9IDUwMCkKYGBgCgojIyMgQ2xlYW4gV29ya3NwYWNlIAoKYGBge3IgUmVtb3ZlIE9iamVjdHMgZnJvbSBFbnZpcm9ubWVudH0Kcm0oZnBzZV90b3RhbF90bSwgZnBzZV9kbl90bSwgZnBzZV92bG50X3RtLCBmcHNlX2Rlbl90bSwgZnBzZV9ncm92ZV90bSwgY3dlX3RvdGFsX3RtLCBjd2VfZG5fdG0sIGN3ZV92bG50X3RtLCBjd2VfZGVuX3RtLCBjd2VfbWNfdG0sIGN3ZV9jdHhfdG0sIGJvdF90b3RhbF90bSwgZnBzZV90aWxlcywgY3dlX3RpbGVzLCBib3RfdGlsZXMsIG1jX3RpbGVzLCBjdHhfdGlsZXMsIGdydl90aWxlcywgZHN0XzIsIGRzdF81LCBkc3QyX3RpbGVzLCBkc3Q1X3RpbGVzKQpgYGAKCiMjIFRhYmxlcyAKCiMjIyBGUFNFIFRhYmxlcyAKCmBgYHtyIEZQU0UgVGFibGVzfQp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieShjcmltZUNhdE5hbWUpICU+JSAKICBjb3VudCgpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIlBhcnQgMSBDcmltZXMiID0gY3JpbWVDYXROYW1lKSAtPiBmcHNlX2NyaW1lQ2F0Cgp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieSh3ZWVrZGF5KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIkRheSBvZiB0aGUgV2VlayIgPSB3ZWVrZGF5KSAtPiBmcHNlX3dlZWtEYXkKCnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lIAogIGdyb3VwX2J5KHZpb2xlbnQpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiQ3JpbWVzIEFnYWluc3QgUGVyc29ucyIgPSB2aW9sZW50KSAtPiBmcHNlX3Zpb2xlbnQKCgp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieShkYXlOaWdodCkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJUaW1lIG9mIERheSIgPSBkYXlOaWdodCkgLT4gZnBzZV9kYXlOaWdodAoKdGlkeVRvdGFsQ3JpbWVzMTggJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieShtb250aFZhcikgJT4lIAogIGNvdW50KGNyaW1lQ2F0TmFtZSkgJT4lIAogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG1vbnRoVmFyLCB2YWx1ZXNfZnJvbSA9ICJOdW1iZXIgb2YgQ3JpbWVzIikgJT4lIAogIHJlcGxhY2UoLiwgaXMubmEoLiksIDApICU+JSAKICByZW5hbWUoLiwgIlBhcnQgMSBDcmltZXMiID0gY3JpbWVDYXROYW1lLCAKICAgICAgICAgIkphbnVhcnkiID0gIjAxIiwKICAgICAgICAgIkZlYnJ1YXJ5IiA9ICIwMiIsCiAgICAgICAgICJNYXJjaCIgPSAiMDMiLAogICAgICAgICAiQXByaWwiID0gIjA0IiwKICAgICAgICAgIk1heSIgPSAiMDUiLAogICAgICAgICAiSnVuZSIgPSAiMDYiLAogICAgICAgICAiSnVseSIgPSAiMDciLAogICAgICAgICAiQXVndXN0IiA9ICIwOCIsCiAgICAgICAgICJTZXB0ZW1iZXIiID0gIjA5IiwKICAgICAgICAgIk9jdG9iZXIiID0gIjEwIiwKICAgICAgICAgIk5vdmVtYmVyIiA9ICIxMSIsCiAgICAgICAgICJEZWNlbWJlciIgPSAiMTIiKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJjb2wiLCBuYW1lID0gIlRvdGFsIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpIC0+IGZwc2VfMjAxOAoKdGlkeVRvdGFsQ3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieShtb250aFZhcikgJT4lIAogIGNvdW50KGNyaW1lQ2F0TmFtZSkgJT4lIAogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG1vbnRoVmFyLCB2YWx1ZXNfZnJvbSA9ICJOdW1iZXIgb2YgQ3JpbWVzIikgJT4lIAogIHJlcGxhY2UoLiwgaXMubmEoLiksIDApICU+JSAKICByZW5hbWUoLiwgIlBhcnQgMSBDcmltZXMiID0gY3JpbWVDYXROYW1lLCAKICAgICAgICAgIkphbnVhcnkiID0gIjAxIiwKICAgICAgICAgIkZlYnJ1YXJ5IiA9ICIwMiIsCiAgICAgICAgICJNYXJjaCIgPSAiMDMiLAogICAgICAgICAiQXByaWwiID0gIjA0IiwKICAgICAgICAgIk1heSIgPSAiMDUiLAogICAgICAgICAiSnVuZSIgPSAiMDYiLAogICAgICAgICAiSnVseSIgPSAiMDciLAogICAgICAgICAiQXVndXN0IiA9ICIwOCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgImNvbCIsIG5hbWUgPSAiVG90YWwiKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgLT4gZnBzZV8yMDE5CgpmcHNlX2xhcmNlbmllcyA8LSB0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBmaWx0ZXIoLiwgY3JpbWVDYXROdW0gPT0gNikKCndyaXRlLmNzdihmcHNlX2xhcmNlbmllcywgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9sYXJjZW5pZXMuY3N2IikpCgpmcHNlX2xhcmNlbmllcyAlPiUgCiAgZ3JvdXBfYnkod2Vla2RheSkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJEYXkgb2YgdGhlIFdlZWsiID0gd2Vla2RheSkgLT4gZnBzZV9sYXJjZW5pZXNfd2Vla0RheQoKZnBzZV9sYXJjZW5pZXMgJT4lIAogIGdyb3VwX2J5KGRheU5pZ2h0KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIlRpbWUgb2YgRGF5IiA9IGRheU5pZ2h0KSAtPiBmcHNlX2xhcmNlbmllc19kYXlOaWdodApgYGAKCgpgYGB7cn0Ka2FibGUoZnBzZV9jcmltZUNhdCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJmcHNlX2NyaW1DYXQuanBlZyIpCgprYWJsZShmcHNlX3dlZWtEYXkpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiZnBzZV93ZWVrRGF5LmpwZWciKQoKa2FibGUoZnBzZV92aW9sZW50KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImZwc2VfdmlvbGVudC5qcGVnIikKCmthYmxlKGZwc2VfZGF5TmlnaHQpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiZnBzZV9kYXlOaWdodC5qcGVnIikKCmthYmxlKGZwc2VfMjAxOCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJmcHNlXzIwMTguanBlZyIpCgprYWJsZShmcHNlXzIwMTkpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiZnBzZV8yMDE5LmpwZWciKQoKa2FibGUoZnBzZV9sYXJjZW5pZXNfd2Vla0RheSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJmcHNlX2xhcmNlbmllc193ZWVrRGF5LmpwZWciKQoKa2FibGUoZnBzZV9sYXJjZW5pZXNfZGF5TmlnaHQpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiZnBzZV9sYXJjZW5pZXNfZGF5TmlnaHQuanBlZyIpCmBgYAoKCiMjIyBDV0UgVGFibGVzIAoKYGBge3IgQ1dFIFRhYmxlc30KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkoY3JpbWVDYXROYW1lKSAlPiUgCiAgY291bnQoKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSkgLT4gY3dlX2NyaW1lQ2F0Cgp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICBncm91cF9ieSh3ZWVrZGF5KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIkRheSBvZiB0aGUgV2VlayIgPSB3ZWVrZGF5KSAtPiBjd2Vfd2Vla0RheQoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkodmlvbGVudCkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJDcmltZXMgQWdhaW5zdCBQZXJzb25zIiA9IHZpb2xlbnQpIC0+IGN3ZV92aW9sZW50CgoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkoZGF5TmlnaHQpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiVGltZSBvZiBEYXkiID0gZGF5TmlnaHQpIC0+IGN3ZV9kYXlOaWdodAoKdGlkeVRvdGFsQ3JpbWVzMTggJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICBncm91cF9ieShtb250aFZhcikgJT4lIAogIGNvdW50KGNyaW1lQ2F0TmFtZSkgJT4lIAogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG1vbnRoVmFyLCB2YWx1ZXNfZnJvbSA9ICJOdW1iZXIgb2YgQ3JpbWVzIikgJT4lIAogIHJlcGxhY2UoLiwgaXMubmEoLiksIDApICU+JSAKICByZW5hbWUoLiwgIlBhcnQgMSBDcmltZXMiID0gY3JpbWVDYXROYW1lLCAKICAgICAgICAgIkphbnVhcnkiID0gIjAxIiwKICAgICAgICAgIkZlYnJ1YXJ5IiA9ICIwMiIsCiAgICAgICAgICJNYXJjaCIgPSAiMDMiLAogICAgICAgICAiQXByaWwiID0gIjA0IiwKICAgICAgICAgIk1heSIgPSAiMDUiLAogICAgICAgICAiSnVuZSIgPSAiMDYiLAogICAgICAgICAiSnVseSIgPSAiMDciLAogICAgICAgICAiQXVndXN0IiA9ICIwOCIsCiAgICAgICAgICJTZXB0ZW1iZXIiID0gIjA5IiwKICAgICAgICAgIk9jdG9iZXIiID0gIjEwIiwKICAgICAgICAgIk5vdmVtYmVyIiA9ICIxMSIsCiAgICAgICAgICJEZWNlbWJlciIgPSAiMTIiKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJjb2wiLCBuYW1lID0gIlRvdGFsIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpIC0+IGN3ZV8yMDE4Cgp0aWR5VG90YWxDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIGdyb3VwX2J5KG1vbnRoVmFyKSAlPiUgCiAgY291bnQoY3JpbWVDYXROYW1lKSAlPiUgCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4pICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gbW9udGhWYXIsIHZhbHVlc19mcm9tID0gIk51bWJlciBvZiBDcmltZXMiKSAlPiUgCiAgcmVwbGFjZSguLCBpcy5uYSguKSwgMCkgJT4lIAogIHJlbmFtZSguLCAiUGFydCAxIENyaW1lcyIgPSBjcmltZUNhdE5hbWUsIAogICAgICAgICAiSmFudWFyeSIgPSAiMDEiLAogICAgICAgICAiRmVicnVhcnkiID0gIjAyIiwKICAgICAgICAgIk1hcmNoIiA9ICIwMyIsCiAgICAgICAgICJBcHJpbCIgPSAiMDQiLAogICAgICAgICAiTWF5IiA9ICIwNSIsCiAgICAgICAgICJKdW5lIiA9ICIwNiIsCiAgICAgICAgICJKdWx5IiA9ICIwNyIsCiAgICAgICAgICJBdWd1c3QiID0gIjA4IikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAiY29sIiwgbmFtZSA9ICJUb3RhbCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAtPiBjd2VfMjAxOQoKY3dlX2xhcmNlbmllcyA8LSB0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICBmaWx0ZXIoLiwgY3JpbWVDYXROdW0gPT0gNikgCgp3cml0ZS5jc3YoY3dlX2xhcmNlbmllcywgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L2xhcmNlbmllcy5jc3YiKSkKCmN3ZV9sYXJjZW5pZXMgJT4lIAogIGdyb3VwX2J5KHdlZWtkYXkpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiRGF5IG9mIHRoZSBXZWVrIiA9IHdlZWtkYXkpIC0+IGN3ZV9sYXJjZW5pZXNfd2Vla0RheQoKY3dlX2xhcmNlbmllcyAlPiUgCiAgZ3JvdXBfYnkoZGF5TmlnaHQpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiVGltZSBvZiBEYXkiID0gZGF5TmlnaHQpIC0+IGN3ZV9sYXJjZW5pZXNfZGF5TmlnaHQKYGBgCgoKYGBge3J9CmthYmxlKGN3ZV9jcmltZUNhdCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJjd2VfY3JpbUNhdC5qcGVnIikKCmthYmxlKGN3ZV93ZWVrRGF5KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImN3ZV93ZWVrRGF5LmpwZWciKQoKa2FibGUoY3dlX3Zpb2xlbnQpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiY3dlX3Zpb2xlbnQuanBlZyIpCgprYWJsZShjd2VfZGF5TmlnaHQpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiY3dlX2RheU5pZ2h0LmpwZWciKQoKa2FibGUoY3dlXzIwMTgpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiY3dlXzIwMTguanBlZyIpCgprYWJsZShjd2VfMjAxOSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJjd2VfMjAxOS5qcGVnIikKCmthYmxlKGN3ZV9sYXJjZW5pZXNfd2Vla0RheSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJjd2VfbGFyY2VuaWVzX3dlZWtEYXkuanBlZyIpCgprYWJsZShjd2VfbGFyY2VuaWVzX2RheU5pZ2h0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImN3ZV9sYXJjZW5pZXNfZGF5TmlnaHQuanBlZyIpCmBgYAoKYGBge3J9CmhlYWQoZnBzZV8yMDE4KSAKd3JpdGUuY3N2KGZwc2VfMjAxOCwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9mcHNlXzIwMTguY3N2IikpCmBgYAoKYGBge3J9CmhlYWQoZnBzZV8yMDE5KQp3cml0ZS5jc3YoZnBzZV8yMDE5LCBmaWxlID0gaGVyZSgicmVzdWx0cy9mcHNlLzIwMTkvYXVndXN0L2Zwc2VfMjAxOS5jc3YiKSkKYGBgCgpgYGB7cn0KaGVhZChjd2VfMjAxOCkKd3JpdGUuY3N2KGN3ZV8yMDE4LCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvY3dlXzIwMTguY3N2IikpCmBgYAoKYGBge3J9CmhlYWQoY3dlXzIwMTkpCndyaXRlLmNzdihjd2VfMjAxOSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L2N3ZV8yMDE5LmNzdiIpKQpgYGAKCiMjIyBCb3RhbmljYWwgSGVpZ2h0cwoKYGBge3IgQk9UIFRhYmxlc30KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDI4KSAlPiUgCiAgZ3JvdXBfYnkoY3JpbWVDYXROYW1lKSAlPiUgCiAgY291bnQoKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSkgLT4gYm90X2NyaW1lQ2F0Cgp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMjgpICU+JSAKICBncm91cF9ieSh3ZWVrZGF5KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIkRheSBvZiB0aGUgV2VlayIgPSB3ZWVrZGF5KSAtPiBib3Rfd2Vla0RheQoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDI4KSAlPiUgCiAgZ3JvdXBfYnkodmlvbGVudCkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJDcmltZXMgQWdhaW5zdCBQZXJzb25zIiA9IHZpb2xlbnQpIC0+IGJvdF92aW9sZW50CgoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDI4KSAlPiUgCiAgZ3JvdXBfYnkoZGF5TmlnaHQpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiVGltZSBvZiBEYXkiID0gZGF5TmlnaHQpIC0+IGJvdF9kYXlOaWdodAoKdGlkeVRvdGFsQ3JpbWVzMTggJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMjgpICU+JSAKICBncm91cF9ieShtb250aFZhcikgJT4lIAogIGNvdW50KGNyaW1lQ2F0TmFtZSkgJT4lIAogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG1vbnRoVmFyLCB2YWx1ZXNfZnJvbSA9ICJOdW1iZXIgb2YgQ3JpbWVzIikgJT4lIAogIHJlcGxhY2UoLiwgaXMubmEoLiksIDApICU+JSAKICByZW5hbWUoLiwgIlBhcnQgMSBDcmltZXMiID0gY3JpbWVDYXROYW1lLCAKICAgICAgICAgIkphbnVhcnkiID0gIjAxIiwKICAgICAgICAgIkZlYnJ1YXJ5IiA9ICIwMiIsCiAgICAgICAgICJNYXJjaCIgPSAiMDMiLAogICAgICAgICAiQXByaWwiID0gIjA0IiwKICAgICAgICAgIk1heSIgPSAiMDUiLAogICAgICAgICAiSnVuZSIgPSAiMDYiLAogICAgICAgICAiSnVseSIgPSAiMDciLAogICAgICAgICAiQXVndXN0IiA9ICIwOCIsCiAgICAgICAgICJTZXB0ZW1iZXIiID0gIjA5IiwKICAgICAgICAgIk9jdG9iZXIiID0gIjEwIiwKICAgICAgICAgIk5vdmVtYmVyIiA9ICIxMSIsCiAgICAgICAgICJEZWNlbWJlciIgPSAiMTIiKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJjb2wiLCBuYW1lID0gIlRvdGFsIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpIC0+IGJvdF8yMDE4CndyaXRlLmNzdihib3RfMjAxOCwgZmlsZSA9IGhlcmUoInJlc3VsdHMvYm90LzIwMTkvYm90XzIwMTguY3N2IikpCgp0aWR5VG90YWxDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAyOCkgJT4lIAogIGdyb3VwX2J5KG1vbnRoVmFyKSAlPiUgCiAgY291bnQoY3JpbWVDYXROYW1lKSAlPiUgCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4pICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gbW9udGhWYXIsIHZhbHVlc19mcm9tID0gIk51bWJlciBvZiBDcmltZXMiKSAlPiUgCiAgcmVwbGFjZSguLCBpcy5uYSguKSwgMCkgJT4lIAogIHJlbmFtZSguLCAiUGFydCAxIENyaW1lcyIgPSBjcmltZUNhdE5hbWUsIAogICAgICAgICAiSmFudWFyeSIgPSAiMDEiLAogICAgICAgICAiRmVicnVhcnkiID0gIjAyIiwKICAgICAgICAgIk1hcmNoIiA9ICIwMyIsCiAgICAgICAgICJBcHJpbCIgPSAiMDQiLAogICAgICAgICAiTWF5IiA9ICIwNSIsCiAgICAgICAgICJKdW5lIiA9ICIwNiIsCiAgICAgICAgICJKdWx5IiA9ICIwNyIsCiAgICAgICAgICJBdWd1c3QiID0gIjA4IikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAiY29sIiwgbmFtZSA9ICJUb3RhbCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAtPiBib3RfMjAxOQp3cml0ZS5jc3YoYm90XzIwMTksIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2JvdC8yMDE5L2JvdF8yMDE5LmNzdiIpKQpgYGAKCmBgYHtyfQprYWJsZShib3RfY3JpbWVDYXQpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiYm90X2NyaW1DYXQuanBlZyIpCgprYWJsZShib3Rfd2Vla0RheSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJib3Rfd2Vla0RheS5qcGVnIikKCmthYmxlKGJvdF92aW9sZW50KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImJvdF92aW9sZW50LmpwZWciKQoKa2FibGUoYm90X2RheU5pZ2h0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImJvdF9kYXlOaWdodC5qcGVnIikKYGBgCgoKIyMgR3JhcGhzL0NoYXJ0cwoKbmVlZCB0byBjaGFuZ2UgZmlsZSBzYXZlIGxvY2F0aW9ucwoKIyMjIEZQU0UgR3JhcGhzIAoKYGBge3IgRlBTRSBDcmltZSBieSBXZWVrZGF5IC0gR3JhcGh9CnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lIAogIGdyb3VwX2J5KHdlZWtkYXkpICU+JSAKICBjb3VudCgpICU+JQogIGdncGxvdCguLCBhZXMoeD13ZWVrZGF5LCB5PW4sIGdyb3VwPTEpKSArCiAgICBnZW9tX2xpbmUoY29sb3I9ImJsdWUiKSArCiAgICBnZW9tX3BvaW50KCkgKyAKICAgIHhsYWIoIkRheSBvZiBXZWVrIikgKyB5bGFiKCJUb3RhbCBDcmltZXMiKSArCiAgICBnZ3RpdGxlKCJGUFNFIFRvdGFsIENyaW1lcyBieSBEYXlzIG9mIHRoZSBXZWVrIikKCmdnc2F2ZShoZXJlKCJyZXN1bHRzL2dyYXBocy9mcHNlX2NyaW1lX3dlZWtkYXkuanBlZyIpLCBkcGkgPSAzMDApCmBgYAoKYGBge3IgRlBTRSBDcmltZSBieSBDYXRlZ29yeSBXZWVrZGF5IC0gR3JhcGh9CnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lIAogIGdyb3VwX2J5KGNyaW1lQ2F0TmFtZSkgJT4lCiAgZ2dwbG90KC4sIGFlcyh3ZWVrZGF5KSkgKwogICAgZ2VvbV9iYXIoYWVzKGZpbGwgPSBjcmltZUNhdE5hbWUpLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgpKSArCiAgICB4bGFiKCJEYXkgb2YgV2VlayIpICsgeWxhYigiVG90YWwgQ3JpbWVzIikgKwogICAgZ2d0aXRsZSgiRlBTRSBDcmltZXMgYnkgRGF5ICYgQ2F0ZWdvcnkiKSArIAogICAgbGFicyhmaWxsID0gIlBhcnQgMSBDcmltZXMiKSArCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKCmdnc2F2ZShoZXJlKCJyZXN1bHRzL2dyYXBocy9mcHNlX2NyaW1lQ2F0X3dlZWtkYXkuanBlZyIpLCBkcGkgPSAzMDApCmBgYAoKCgpgYGB7ciBGUFNFIENyaW1lIGJ5IFRpbWUgb2YgRGF5IH0KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgZ3JvdXBfYnkoZGF5TmlnaHQpICU+JQogIGNvdW50KCkgJT4lIAogIGdncGxvdCguLCBhZXMoeD1kYXlOaWdodCwgeT1uLCBmaWxsID0gZGF5TmlnaHQpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKCksIGNvbG91cj0iYmxhY2siKSArCiAgICB4bGFiKCJUaW1lIG9mIERheSIpICsgeWxhYigiVG90YWwgQ3JpbWVzIikgKwogICAgZ2d0aXRsZSgiRlBTRSBDcmltZXMgYnkgVGltZSBvZiBEYXkiKSArIAogICAgbGFicyhmaWxsID0gIlRpbWUiKQoKZ2dzYXZlKGhlcmUoInJlc3VsdHMvZ3JhcGhzL2Zwc2VfY3JpbWVfdGltZURheS5qcGVnIiksIGRwaSA9IDMwMCkKYGBgCgoKIyMjIENXRSBHcmFwaHMgCgpgYGB7ciBDV0UgQ3JpbWUgYnkgV2Vla2RheSAtIEdyYXBofQp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICBncm91cF9ieSh3ZWVrZGF5KSAlPiUgCiAgY291bnQoKSAlPiUKICBnZ3Bsb3QoLiwgYWVzKHg9d2Vla2RheSwgeT1uLCBncm91cD0xKSkgKwogICAgZ2VvbV9saW5lKGNvbG9yPSJibHVlIikgKwogICAgZ2VvbV9wb2ludCgpICsgCiAgICB4bGFiKCJEYXkgb2YgV2VlayIpICsgeWxhYigiVG90YWwgQ3JpbWVzIikgKwogICAgZ2d0aXRsZSgiQ1dFIFRvdGFsIENyaW1lcyBieSBEYXlzIG9mIHRoZSBXZWVrIikKCmdnc2F2ZShoZXJlKCJyZXN1bHRzL2dyYXBocy9jd2VfY3JpbWVfd2Vla2RheS5qcGVnIiksIGRwaSA9IDMwMCkKYGBgCgpgYGB7ciBDV0UgQ3JpbWUgYnkgQ2F0ZWdvcnkgV2Vla2RheSAtIEdyYXBofQp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICBncm91cF9ieShjcmltZUNhdE5hbWUpICU+JQogIGdncGxvdCguLCBhZXMod2Vla2RheSkpICsKICAgIGdlb21fYmFyKGFlcyhmaWxsID0gY3JpbWVDYXROYW1lKSwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoKSkgKwogICAgeGxhYigiRGF5IG9mIFdlZWsiKSArIHlsYWIoIlRvdGFsIENyaW1lcyIpICsKICAgIGdndGl0bGUoIkNXRSBDcmltZXMgYnkgRGF5ICYgQ2F0ZWdvcnkiKSArIAogICAgbGFicyhmaWxsID0gIlBhcnQgMSBDcmltZXMiKSArCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKCmdnc2F2ZShoZXJlKCJyZXN1bHRzL2dyYXBocy9jd2VfY3JpbWVDYXRfd2Vla2RheS5qcGVnIiksIGRwaSA9IDMwMCkKCmBgYAoKCgpgYGB7ciBDV0UgQ3JpbWUgYnkgVGltZSBvZiBEYXkgfQp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICBncm91cF9ieShkYXlOaWdodCkgJT4lCiAgY291bnQoKSAlPiUgCiAgZ2dwbG90KC4sIGFlcyh4PWRheU5pZ2h0LCB5PW4sIGZpbGwgPSBkYXlOaWdodCkpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoKSwgY29sb3VyPSJibGFjayIpICsKICAgIHhsYWIoIlRpbWUgb2YgRGF5IikgKyB5bGFiKCJUb3RhbCBDcmltZXMiKSArCiAgICBnZ3RpdGxlKCJDV0UgQ3JpbWVzIGJ5IFRpbWUgb2YgRGF5IikgKyAKICAgIGxhYnMoZmlsbCA9ICJUaW1lIikgCgpnZ3NhdmUoaGVyZSgicmVzdWx0cy9ncmFwaHMvY3dlX2NyaW1lX3RpbWVEYXkuanBlZyIpLCBkcGkgPSAzMDApCmBgYAojIyMgQk9UIAoKYGBge3IgQk9UIENyaW1lIGJ5IFdlZWtkYXkgLSBHcmFwaH0KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDI4KSAlPiUgCiAgZ3JvdXBfYnkod2Vla2RheSkgJT4lIAogIGNvdW50KCkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4PXdlZWtkYXksIHk9biwgZ3JvdXA9MSkpICsKICAgIGdlb21fbGluZShjb2xvcj0iYmx1ZSIpICsKICAgIGdlb21fcG9pbnQoKSArIAogICAgeGxhYigiRGF5IG9mIFdlZWsiKSArIHlsYWIoIlRvdGFsIENyaW1lcyIpICsKICAgIGdndGl0bGUoIkJPVCBUb3RhbCBDcmltZXMgYnkgRGF5cyBvZiB0aGUgV2VlayIpCgpnZ3NhdmUoaGVyZSgicmVzdWx0cy9ncmFwaHMvYm90X2NyaW1lX3dlZWtkYXkuanBlZyIpLCBkcGkgPSAzMDApCmBgYAoK